Beispiel #1
0
    def update_invite_contact(request_user, request_data, contact):
        """Update an existing Third Party invite contact.

        :param (User) request_user: Inviting user.
        :param (dict) request_data: Invite contact update parameters.
        :param (Contact) contact: Contact to update
        """
        contact.load_attributes(request_data, ["name", "email"])
        contact.organisation = InviteThirdPartyAPI.update_invitee_org(
            request_user, request_data, contact.organisation
        )
        if phone := request_data.get("phone"):
            contact.phone = convert_to_e164(phone)
Beispiel #2
0
    def create_contact(
        name,
        email,
        created_by,
        organisation=None,
        phone=None,
        post_code=None,
        country=None,
        address=None,
    ):
        """Create a new contact record

        Arguments:
            name {str} -- Contact name
            email {str} -- Contact email
            created_by {User} -- The user creating the contact

        Keyword Arguments:
            organisation {Organisation} -- Optional organisation
                   to associate the contact with (default: {None})
            phone {str} -- Contact phon enumber. Will be E164 formatted (default: {None})
            post_code {str} -- Contact post code (default: {None})
            country {str} -- Contact ISO country code (default: {None})

        Returns:
            Contact -- Contact model
        """
        contact = Contact(
            created_by=created_by,
            name=name,
            email=email.lower() if email else None,
            user_context=created_by,
        )
        country = (
            country or organisation.country.code if organisation and organisation.country else "GB"
        )
        contact.organisation = organisation
        if address is None and organisation:
            contact.address_from_org(organisation)
        else:
            contact.address = address
        contact.phone = convert_to_e164(phone, country)
        contact.country = country
        contact.post_code = post_code
        contact.save()
        return contact
Beispiel #3
0
    def create_user_invite(self, user_email, organisation, invited_by, meta):
        """
        Create an invite for a user to join an organisation as a direct employee.
        The invite's meta data contains all the parameters required to create the user
        record once the user accepts the invite.
        A contact record will be created for this user, which will later be re-assigned
        to the user upon completing registration. Note that at this stage the organisation is NOT
        set against the contact, to prevent it appearing until the user accepts. Then the org
        assignment is made.
        If an invite is already present and not responded to it will be refreshed.

        :param (str) user_email: The user to be invited.
        :param (Organisation) organisation: The organisation invited to
        :param (User) invited_by: The user creating the invitation.
        :param (dict) meta: invite meta data.
        """
        created = True
        user_email = user_email.lower()
        try:
            invite = Invitation.objects.get(organisation=organisation,
                                            email=user_email,
                                            deleted_at__isnull=True)
            created = False
        except Invitation.DoesNotExist:
            invite = Invitation.objects.create(
                organisation=organisation,
                email=user_email,
                user_context=invited_by,
            )
        if invite.accepted_at:
            raise InviteAlreadyAccepted(
                f"The user {user_email} has already been invited to {organisation} "
                "and has accepted the invite.")
        if (not created and (timezone.now() - invite.created_at).seconds / 3600
                > settings.ORGANISATION_INVITE_DURATION_HOURS):
            invite = invite.recreate()
        invite.created_by = invited_by
        invite.create_codes()
        if meta and meta.get("email"):
            meta["email"] = meta["email"].lower()
        invite.meta = meta
        phone = convert_to_e164(
            meta.get("phone")) if meta.get("phone") else None
        invite.contact = Contact.objects.create_contact(
            created_by=invited_by,
            name=meta["name"],
            email=user_email,
            phone=phone,
            country=meta.get("country"),
        )
        invite.save()
        invite.send(
            sent_by=invited_by,
            direct=False,
            template_key="NOTIFY_INVITE_ORGANISATION_USER",
            context={
                "login_url":
                f"{settings.PUBLIC_ROOT_URL}/invitation/{invite.code}/for/{organisation.id}/"  # noqa: E501
            },
        )
        return invite
Beispiel #4
0
    def post(self,
             request,
             organisation_id,
             invitation_id=None,
             *args,
             **kwargs):  # noqa: C901
        from invitations.models import Invitation

        case_spec = request.data.get("case_spec") or []
        data = pluck(request.data, ["email", "name", "group", "phone"])
        data["is_active"] = request.data.get("active",
                                             "False").upper() == "TRUE"
        organisation = Organisation.objects.get(id=organisation_id)
        user = None
        contact = None
        data["case_spec"] = json.loads(case_spec) if isinstance(
            case_spec, str) else case_spec
        if invitation_id:
            try:
                invite = Invitation.objects.get(
                    id=invitation_id,
                    organisation=organisation,
                    deleted_at__isnull=True,
                )
                if invite.accepted_at or data["email"] != invite.email:
                    invitation_id = None
                else:
                    if data and data.get("email"):
                        data["email"] = data["email"].lower()
                    invite.meta = data
                    invite.save()
                    contact = invite.contact
                    _save_contact = False
                    if contact.phone != data.get("phone"):
                        contact.phone = convert_to_e164(
                            data["phone"],
                            data.get("country",
                                     request.user.userprofile.country.code),
                        )
                        _save_contact = True
                    if contact.name != data.get("name"):
                        contact.name = data["name"]
                        _save_contact = True
                    if _save_contact:
                        contact.save()
            except Invitation.DoesNotExist:
                raise NotFoundApiExceptions("Invalid invitation")
        if not invitation_id:
            try:
                user = User.objects.get(
                    email=data.get("email").strip().lower())
                # if the user already exists, send an email to the user and leave it at that.
                invite = Invitation.objects.invite_existing_user(
                    user=user,
                    organisation=organisation,
                    invited_by=request.user,
                    name=data.get("name"),
                )
            except User.DoesNotExist:
                invite = Invitation.objects.create_user_invite(
                    user_email=data["email"].lower(),
                    organisation=organisation,
                    invited_by=request.user,
                    meta=data,
                )
        return ResponseSuccess({
            "result": {
                "user": user.to_dict() if user else None,
                "contact": contact.to_dict() if contact else None,
                "invite": invite.to_dict(),
            }
        })
Beispiel #5
0
    def post(self,
             request,
             organisation_id,
             user_id=None,
             invitation_id=None,
             *args,
             **kwargs):

        group = None
        password = None
        invitation = None
        contact = None
        cases = None
        errors = {}

        # If this is not an organisation owner, they can only update their own details
        try:
            organisation = Organisation.objects.get(id=organisation_id)
        except Organisation.DoesNotExist:
            raise NotFoundApiExceptions("Invalid parameters or access denied")
        if user_id and (user_id != request.user.id):
            if not request.user.groups.filter(
                    name=SECURITY_GROUP_ORGANISATION_OWNER).exists():
                raise InvalidAccess(
                    "Only organisation owners can update other members")
        elif not user_id and invitation_id:
            try:
                invitation = Invitation.objects.get(id=invitation_id,
                                                    organisation=organisation)
            except Invitation.DoesNotExist:
                raise NotFoundApiExceptions(
                    "Invalid parameters of access denied")
        request_data = request.data.dict()
        if invitation:
            request_data["group"] = invitation.meta["group"]
            request_data["active"] = invitation.meta["is_active"]
            request_data["case_spec"] = invitation.meta["case_spec"]
            request_data["email"] = invitation.email
            request_data["contact"] = invitation.contact
            organisation = invitation.organisation
        if request_data.get("group"):
            try:
                group = Group.objects.filter(
                    name__in=SECURITY_GROUPS_PUBLIC).get(
                        name=request_data.get("group"))
            except Group.DoesNotExist:
                errors["group"] = "Invalid security group"
        if not request_data.get("email"):
            errors["email"] = "Email is required"
        if not request_data.get("name"):
            errors["name"] = "Name is required"
        if not user_id:
            try:
                User.objects.get(email=request.data.get("email"))
                errors["email"] = "User email already exists"
            except User.DoesNotExist:
                pass
        if request_data.get("password"):
            if request_data.get("password") == request_data.get(
                    "password_confirm"):
                password = request_data.get("password")
                try:
                    invalid_password = validate_password(password)
                    if invalid_password:
                        errors["password"] = invalid_password
                except ValidationError as exc:
                    errors["password"] = exc.messages
            else:
                errors["password"] = "******"
        elif not user_id:
            errors["password"] = "******"
        if request_data.get(
                "terms_required") and not request_data.get("terms"):
            errors["terms"] = "Please accept the terms of use"

        if not errors:
            if user_id is not None:
                user = User.objects.get(
                    id=user_id, organisationuser__organisation=organisation)
            else:
                user = User()
            # contact = user.contact
            user, _ = user.load_attributes(request_data)
            # contact.phone = request.data.get('phone', contact.phone)
            if request.data.get("active") is not None:
                is_active = request_data.get("active") in TRUTHFUL_INPUT_VALUES
                if is_active != user.is_active and not (user == request.user
                                                        and not is_active):
                    user.is_active = is_active
            if password:
                user.set_password(request_data.get("password"))
            user.save()
            if group:
                user.groups.clear()
                user.groups.add(group)
                organisation.assign_user(user, group)
            cases = request_data.get("case_spec")
            phone = request_data.get("phone")
            if cases:
                cases = json.loads(cases) if isinstance(cases, str) else cases
                user.set_cases(organisation, cases, request.user)
            if request.data.getlist("unassign_case_id"):
                for case_id in request.data.getlist("unassign_case_id"):
                    user.remove_from_case(case_id, created_by=request.user)
                    # todo: remove contact from case too
            profile = user.userprofile
            if profile.contact:
                contact = profile.contact
                contact.organisation = organisation
                contact.address = request_data.get("address", contact.address)
                contact.country = request.data.get("country_code",
                                                   contact.country.code)
                if not contact.address:
                    contact.address_from_org(organisation)
                contact.phone = convert_to_e164(phone, str(contact.country))
                contact._disable_audit = True
                contact.save()
            if not profile.email_verified_at or not profile.email_verify_code:
                profile.verify_email()
            return ResponseSuccess(
                {"result": user.to_dict(organisation=organisation)},
                http_status=status.HTTP_201_CREATED,
            )
        else:
            raise InvalidRequestParams(detail={"errors": errors})