Beispiel #1
0
def delete_users_orgs(**kwargs):
    if not settings.DEMO_MODE:
        return

    logger.info("delete_users_orgs.start")
    # delete everything older than a day
    cutoff_time = timezone.now() - timedelta(days=1)

    # note this only runs in demo mode (not SaaS) so the underlying tables here are small
    org_list = Organization.objects.filter(
        demoorganization__date_assigned__lte=cutoff_time,
        demoorganization__status=DemoOrgStatus.ACTIVE,
        status__in=(
            OrganizationStatus.ACTIVE,
            OrganizationStatus.PENDING_DELETION,
        ),
    )

    # first mark orgs for deletion
    org_list.update(status=OrganizationStatus.PENDING_DELETION)

    # next delete the users
    User.objects.filter(demouser__isnull=False, demouser__date_assigned__lte=cutoff_time).delete()

    # now finally delete the orgs
    for org in org_list:
        # apply async so if so we continue if one org aborts
        logger.info("delete_initializing_orgs.delete", extra={"organization_slug": org.slug})
        delete_organization.apply_async(kwargs={"object_id": org.id})
Beispiel #2
0
    def delete(self, request, organization):
        """
        Delete an Organization
        ``````````````````````

        Schedules an organization for deletion.  This API endpoint cannot
        be invoked without a user context for security reasons.  This means
        that at present an organization can only be deleted from the
        Sentry UI.

        Deletion happens asynchronously and therefor is not immediate.
        However once deletion has begun the state of a project changes and
        will be hidden from most public views.

        :pparam string organization_slug: the slug of the organization the
                                          team should be created for.
        :auth: required, user-context-needed
        """
        if not request.user.is_authenticated():
            return Response({'detail': 'This request requires a user.'},
                            status=401)

        if organization.is_default:
            return Response({'detail': ERR_DEFAULT_ORG}, status=400)

        updated = Organization.objects.filter(
            id=organization.id,
            status=OrganizationStatus.VISIBLE,
        ).update(status=OrganizationStatus.PENDING_DELETION)
        if updated:
            transaction_id = uuid4().hex
            countdown = 86400

            entry = self.create_audit_entry(
                request=request,
                organization=organization,
                target_object=organization.id,
                event=AuditLogEntryEvent.ORG_REMOVE,
                data=organization.get_audit_log_data(),
                transaction_id=transaction_id,
            )

            organization.send_delete_confirmation(entry, countdown)

            delete_organization.apply_async(
                kwargs={
                    'object_id': organization.id,
                    'transaction_id': transaction_id,
                },
                countdown=countdown,
            )

            delete_logger.info('object.delete.queued',
                               extra={
                                   'object_id': organization.id,
                                   'transaction_id': transaction_id,
                                   'model': Organization.__name__,
                               })

        return Response(status=204)
Beispiel #3
0
def delete_initializing_orgs(**kwargs):
    """
    Deletes orgs that are still in the initializing state.
    This happens if Sentry is killed while an organization is being created.
    """
    if not settings.DEMO_MODE:
        return

    logger.info("delete_initializing_orgs.start")
    # delete everything older than MAX_INITIALIZATION_TIME
    max_init_time = settings.DEMO_DATA_GEN_PARAMS["MAX_INITIALIZATION_TIME"]
    cutoff_time = timezone.now() - timedelta(minutes=max_init_time)

    # note this only runs in demo mode (not SaaS) so the underlying tables here are small
    org_list = Organization.objects.filter(
        demoorganization__date_added__lte=cutoff_time,
        demoorganization__status=DemoOrgStatus.INITIALIZING,
    )

    # first mark orgs for deletion
    org_list.update(status=OrganizationStatus.PENDING_DELETION)

    # now finally delete the orgs
    for org in org_list:
        # apply async so if so we continue if one org aborts
        logger.info("delete_initializing_orgs.delete", extra={"organization_slug": org.slug})
        delete_organization.apply_async(kwargs={"object_id": org.id})

    # build up the org buffer at the end to replace the orgs being removed
    build_up_org_buffer()
    def handle(self, request, organization):
        if organization.is_default:
            messages.add_message(request, messages.ERROR, ERR_DEFAULT_ORG)
            return self.redirect(reverse('sentry-organization-home', args=[
                organization.slug
            ]))

        form = self.get_form(request, organization)
        if form.is_valid():
            if organization.status != OrganizationStatus.PENDING_DELETION:
                organization.update(status=OrganizationStatus.PENDING_DELETION)

                delete_organization.apply_async(kwargs={
                    'object_id': organization.id,
                }, countdown=60 * 5)

            messages.add_message(request, messages.SUCCESS,
                MSG_REMOVE_SUCCESS % (organization.name,))

            return self.redirect(reverse('sentry'))

        context = {
            'form': form,
            'team_list': organization.team_set.all(),
        }

        return self.respond('sentry/remove-organization.html', context)
    def handle(self, request, organization):
        if organization.is_default:
            messages.add_message(request, messages.ERROR, ERR_DEFAULT_ORG)
            return self.redirect(reverse('sentry-organization-home', args=[
                organization.slug
            ]))

        form = self.get_form(request, organization)
        if form.is_valid():
            if organization.status != OrganizationStatus.PENDING_DELETION:
                organization.update(status=OrganizationStatus.PENDING_DELETION)

                delete_organization.apply_async(kwargs={
                    'object_id': organization.id,
                }, countdown=60 * 5)

            messages.add_message(request, messages.SUCCESS,
                MSG_REMOVE_SUCCESS % (organization.name,))

            return self.redirect(reverse('sentry'))

        context = {
            'form': form,
            'team_list': organization.team_set.all(),
        }

        return self.respond('sentry/remove-organization.html', context)
    def delete(self, request, organization):
        """
        Delete an Organization
        ``````````````````````

        Schedules an organization for deletion.  This API endpoint cannot
        be invoked without a user context for security reasons.  This means
        that at present an organization can only be deleted from the
        Sentry UI.

        Deletion happens asynchronously and therefor is not immediate.
        However once deletion has begun the state of a project changes and
        will be hidden from most public views.

        :pparam string organization_slug: the slug of the organization the
                                          team should be created for.
        :auth: required, user-context-needed
        """
        if not request.user.is_authenticated():
            return Response({'detail': 'This request requires a user.'},
                            status=401)

        if organization.is_default:
            return Response({'detail': ERR_DEFAULT_ORG}, status=400)

        updated = Organization.objects.filter(
            id=organization.id,
            status=OrganizationStatus.VISIBLE,
        ).update(status=OrganizationStatus.PENDING_DELETION)
        if updated:
            transaction_id = uuid4().hex
            countdown = 86400

            entry = self.create_audit_entry(
                request=request,
                organization=organization,
                target_object=organization.id,
                event=AuditLogEntryEvent.ORG_REMOVE,
                data=organization.get_audit_log_data(),
                transaction_id=transaction_id,
            )

            organization.send_delete_confirmation(entry, countdown)

            delete_organization.apply_async(
                kwargs={
                    'object_id': organization.id,
                    'transaction_id': transaction_id,
                },
                countdown=countdown,
            )

            delete_logger.info('object.delete.queued', extra={
                'object_id': organization.id,
                'transaction_id': transaction_id,
                'model': Organization.__name__,
            })

        return Response(status=204)
    def handle(self, request, organization):
        if organization.is_default:
            messages.add_message(request, messages.ERROR, ERR_DEFAULT_ORG)
            return self.redirect(reverse('sentry-organization-home', args=[organization.slug]))

        form = self.get_form(request, organization)
        if form.is_valid():
            updated = Organization.objects.filter(
                id=organization.id,
                status=OrganizationStatus.VISIBLE,
            ).update(status=OrganizationStatus.PENDING_DELETION)
            if updated:
                transaction_id = uuid4().hex
                countdown = 86400

                entry = self.create_audit_entry(
                    request=request,
                    organization=organization,
                    target_object=organization.id,
                    event=AuditLogEntryEvent.ORG_REMOVE,
                    data=organization.get_audit_log_data(),
                    transaction_id=transaction_id,
                )

                organization.send_delete_confirmation(entry, countdown)

                delete_organization.apply_async(
                    kwargs={
                        'object_id': organization.id,
                        'transaction_id': transaction_id,
                        'actor_id': request.user.id,
                    },
                    countdown=countdown,
                )

                delete_logger.info(
                    'object.delete.queued',
                    extra={
                        'object_id': organization.id,
                        'transaction_id': transaction_id,
                        'model': Organization.__name__,
                    }
                )

            messages.add_message(
                request, messages.SUCCESS, MSG_REMOVE_SUCCESS % (organization.name, )
            )

            return self.redirect(reverse('sentry'))

        context = {
            'form': form,
            'team_list': organization.team_set.all(),
        }

        return self.respond('sentry/remove-organization.html', context)
    def handle(self, request, organization):
        if organization.is_default:
            messages.add_message(request, messages.ERROR, ERR_DEFAULT_ORG)
            return self.redirect(reverse('sentry-organization-home', args=[organization.slug]))

        form = self.get_form(request, organization)
        if form.is_valid():
            updated = Organization.objects.filter(
                id=organization.id,
                status=OrganizationStatus.VISIBLE,
            ).update(status=OrganizationStatus.PENDING_DELETION)
            if updated:
                transaction_id = uuid4().hex
                countdown = 86400

                entry = self.create_audit_entry(
                    request=request,
                    organization=organization,
                    target_object=organization.id,
                    event=AuditLogEntryEvent.ORG_REMOVE,
                    data=organization.get_audit_log_data(),
                    transaction_id=transaction_id,
                )

                organization.send_delete_confirmation(entry, countdown)

                delete_organization.apply_async(
                    kwargs={
                        'object_id': organization.id,
                        'transaction_id': transaction_id,
                    },
                    countdown=countdown,
                )

                delete_logger.info(
                    'object.delete.queued',
                    extra={
                        'object_id': organization.id,
                        'transaction_id': transaction_id,
                        'model': Organization.__name__,
                    }
                )

            messages.add_message(
                request, messages.SUCCESS, MSG_REMOVE_SUCCESS % (organization.name, )
            )

            return self.redirect(reverse('sentry'))

        context = {
            'form': form,
            'team_list': organization.team_set.all(),
        }

        return self.respond('sentry/remove-organization.html', context)
def create_demo_org(quick=False) -> Organization:
    # wrap the main org setup in transaction
    with transaction.atomic():
        name = generate_random_name()

        slug = slugify(name)

        demo_org = DemoOrganization.create_org(name=name, slug=slug)
        org = demo_org.organization

        logger.info("create_demo_org.created_org", {"organization_slug": slug})

        owner = User.objects.get(email=settings.DEMO_ORG_OWNER_EMAIL)
        OrganizationMember.objects.create(organization=org, user=owner, role=roles.get_top_dog().id)

        team = org.team_set.create(name=org.name)
        python_project = Project.objects.create(name="Python", organization=org, platform="python")
        python_project.add_team(team)

        react_project = Project.objects.create(
            name="React", organization=org, platform="javascript-react"
        )
        react_project.add_team(team)

        # we'll be adding transactions later
        Project.objects.filter(organization=org).update(
            flags=F("flags").bitor(Project.flags.has_transactions)
        )

    logger.info(
        "create_demo_org.post-transaction",
        extra={"organization_slug": org.slug, "quick": quick},
    )
    try:
        handle_react_python_scenario(react_project, python_project, quick=quick)
    except Exception as e:
        logger.error(
            "create_demo_org.population_error",
            extra={"organization_slug": org.slug, "quick": quick, "error": str(e)},
        )
        # delete the organization if data population fails
        org.status = OrganizationStatus.PENDING_DELETION
        org.save()
        delete_organization.apply_async(kwargs={"object_id": org.id})
        raise

    # update the org status now that it's populated
    demo_org.status = DemoOrgStatus.PENDING
    demo_org.save()

    return org
 def handle_delete(self, request, organization):
     """
     This method exists as a way for getsentry to override this endpoint with less duplication.
     """
     if not request.user.is_authenticated:
         return self.respond({"detail": ERR_NO_USER}, status=401)
     if organization.is_default:
         return self.respond({"detail": ERR_DEFAULT_ORG}, status=400)
     updated = Organization.objects.filter(
         id=organization.id, status=OrganizationStatus.VISIBLE).update(
             status=OrganizationStatus.PENDING_DELETION)
     if updated:
         transaction_id = uuid4().hex
         countdown = 86400
         entry = self.create_audit_entry(
             request=request,
             organization=organization,
             target_object=organization.id,
             event=AuditLogEntryEvent.ORG_REMOVE,
             data=organization.get_audit_log_data(),
             transaction_id=transaction_id,
         )
         organization.send_delete_confirmation(entry, countdown)
         delete_organization.apply_async(
             kwargs={
                 "object_id": organization.id,
                 "transaction_id": transaction_id,
                 "actor_id": request.user.id,
             },
             countdown=countdown,
         )
         delete_logger.info(
             "object.delete.queued",
             extra={
                 "object_id": organization.id,
                 "transaction_id": transaction_id,
                 "model": Organization.__name__,
             },
         )
     context = serialize(
         organization,
         request.user,
         org_serializers.DetailedOrganizationSerializerWithProjectsAndTeams(
         ),
         access=request.access,
     )
     return self.respond(context, status=202)
    def handle(self, request, organization):
        if organization.is_default:
            messages.add_message(request, messages.ERROR, ERR_DEFAULT_ORG)
            return self.redirect(
                reverse('sentry-organization-home', args=[organization.slug]))

        form = self.get_form(request, organization)
        if form.is_valid():
            transaction_id = uuid4().hex
            logging.getLogger('sentry.deletions').info(
                'remove.organization',
                extra={
                    'organization_id': organization.id,
                    'organization_slug': organization.slug,
                    'actor_id': request.user.id,
                    'transaction_id': transaction_id,
                    'ip_address': request.META['REMOTE_ADDR'],
                })

            updated = Organization.objects.filter(
                id=organization.id,
                status=OrganizationStatus.VISIBLE,
            ).update(status=OrganizationStatus.PENDING_DELETION)
            if updated:
                delete_organization.apply_async(
                    kwargs={
                        'object_id': organization.id,
                        'transaction_id': transaction_id,
                    },
                    countdown=86400,
                )

            messages.add_message(request, messages.SUCCESS,
                                 MSG_REMOVE_SUCCESS % (organization.name, ))

            return self.redirect(reverse('sentry'))

        context = {
            'form': form,
            'team_list': organization.team_set.all(),
        }

        return self.respond('sentry/remove-organization.html', context)
Beispiel #12
0
def delete_users_orgs(**kwargs):
    if not settings.DEMO_MODE:
        return

    # delete everything older than a day
    cutoff_time = timezone.now() - timedelta(days=1)

    # first mark orgs for deletion
    # note this only runs in demo mode (not SaaS) so the underlying tables here are small
    org_list = Organization.objects.filter(
        date_added__lte=cutoff_time,
        flags=F("flags").bitor(Organization.flags["demo_mode"]))
    org_list.update(status=OrganizationStatus.PENDING_DELETION)

    # next delete the users
    User.objects.filter(date_joined__lte=cutoff_time,
                        flags=F("flags").bitor(
                            User.flags["demo_mode"])).delete()

    # now finally delete the orgs
    for org in org_list:
        # apply async so if so we continue if one org aborts
        delete_organization.apply_async(kwargs={"object_id": org.id})
Beispiel #13
0
def create_demo_org(quick=False) -> Organization:
    with sentry_sdk.start_transaction(op="create_demo_org", name="create_demo_org", sampled=True):
        sentry_sdk.set_tag("quick", quick)
        # wrap the main org setup in transaction
        with transaction.atomic():
            name = generate_random_name()

            slug = slugify(name)

            projects = []

            demo_org = DemoOrganization.create_org(name=name, slug=slug)
            org = demo_org.organization

            logger.info("create_demo_org.created_org", {"organization_slug": slug})

            owner = User.objects.get(email=settings.DEMO_ORG_OWNER_EMAIL)
            OrganizationMember.objects.create(
                organization=org, user=owner, role=roles.get_top_dog().id
            )

            team = org.team_set.create(name=org.name)

            def create_project(name, platform):
                project = Project.objects.create(name=name, organization=org, platform=platform)
                project.add_team(team)
                projects.append(project)
                return project

            python_project = create_project("Python", "python")
            react_project = create_project("React", "javascript-react")
            react_native_project = create_project("React-Native", "react-native")
            android_project = create_project("Android", "android")
            ios_project = create_project("iOS", "apple-ios")

            populate_org_members(org, team)
            # we'll be adding transactions later
            Project.objects.filter(organization=org).update(
                flags=F("flags").bitor(Project.flags.has_transactions)
            )

        logger.info(
            "create_demo_org.post-transaction",
            extra={"organization_slug": org.slug, "quick": quick},
        )

        with sentry_sdk.start_span(op="handle_react_python_mobile_scenario"):
            try:
                data_population = DataPopulation(org, quick=quick)
                data_population.generate_releases(projects)
                data_population.generate_saved_search(projects)
                data_population.handle_react_python_scenario(react_project, python_project)
                data_population.handle_mobile_scenario(
                    ios_project, android_project, react_native_project
                )

            except Exception as e:
                logger.error(
                    "create_demo_org.population_error",
                    extra={"organization_slug": org.slug, "quick": quick, "error": str(e)},
                )
                # delete the organization if data population fails
                org.status = OrganizationStatus.PENDING_DELETION
                org.save()
                delete_organization.apply_async(kwargs={"object_id": org.id})
                raise

        # update the org status now that it's populated
        demo_org.status = DemoOrgStatus.PENDING
        demo_org.save()

        logger.info(
            "create_demo_org.complete",
            extra={"organization_slug": org.slug, "quick": quick},
        )

        return org