Exemplo n.º 1
0
class GroupTagValue(Model):
    """
    Stores the total number of messages seen by a group matching
    the given filter.
    """
    project = models.ForeignKey('sentry.Project', null=True, related_name='grouptag')
    group = models.ForeignKey('sentry.Group', related_name='grouptag')
    times_seen = BoundedPositiveIntegerField(default=0)
    key = models.CharField(max_length=MAX_TAG_KEY_LENGTH)
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    last_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)
    first_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_messagefiltervalue'
        unique_together = (('project', 'key', 'value', 'group'),)

    __repr__ = sane_repr('project_id', 'group_id', 'key', 'value')

    def save(self, *args, **kwargs):
        if not self.first_seen:
            self.first_seen = self.last_seen
        super(GroupTag, self).save(*args, **kwargs)
Exemplo n.º 2
0
    def create(self, id, secret=None, homepage=None,
               capabilities_url=None, room_id=None, token_url=None,
               capdoc=None):
        if homepage is None and capdoc is not None:
            homepage = capdoc['links']['homepage']
        if token_url is None and capdoc is not None:
            token_url = capdoc['capabilities']['oauth2Provider']['tokenUrl']
        if capabilities_url is None and capdoc is not None:
            capabilities_url = capdoc['links']['self']
        if capdoc is not None:
            api_base_url = capdoc['capabilities']['hipchatApiProvider']['url']
        else:
            api_base_url = capabilities_url.rsplit('/', 1)[0]
        installed_from = token_url and base_url(token_url) or None

        return BaseManager.create(self,
            id=id,
            room_id=room_id,
            secret=secret,
            homepage=homepage,
            token_url=token_url,
            capabilities_url=capabilities_url,
            api_base_url=api_base_url,
            installed_from=installed_from,
        )
Exemplo n.º 3
0
    def create_or_update_app(self,
                             sync_id,
                             app_id,
                             project,
                             data=None,
                             platform=DSymPlatform.GENERIC,
                             no_fetch=False):
        if data is None:
            data = {}
        if not no_fetch:
            _auto_enrich_data(data, app_id, platform)
        existing_app = DSymApp.objects.filter(app_id=app_id,
                                              project=project).first()
        if existing_app is not None:
            now = timezone.now()
            existing_app.update(
                sync_id=sync_id,
                data=data,
                last_synced=now,
            )
            return existing_app

        return BaseManager.create(self,
                                  sync_id=sync_id,
                                  app_id=app_id,
                                  data=data,
                                  project=project,
                                  platform=platform)
class TagValue(Model):
    """
    Stores references to available filters.
    """
    __core__ = False

    project_id = BoundedPositiveIntegerField(db_index=True, null=True)
    key = models.CharField(max_length=MAX_TAG_KEY_LENGTH)
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    data = GzippedDictField(blank=True, null=True)
    times_seen = BoundedPositiveIntegerField(default=0)
    last_seen = models.DateTimeField(default=timezone.now,
                                     db_index=True,
                                     null=True)
    first_seen = models.DateTimeField(default=timezone.now,
                                      db_index=True,
                                      null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_filtervalue'
        unique_together = (('project_id', 'key', 'value'), )
        index_together = (('project_id', 'key', 'last_seen'), )

    __repr__ = sane_repr('project_id', 'key', 'value')

    def get_label(self):
        from sentry import tagstore

        return tagstore.get_tag_value_label(self.key, self.value)
Exemplo n.º 5
0
    def create(self,
               id,
               secret=None,
               homepage=None,
               capabilities_url=None,
               room_id=None,
               token_url=None,
               capdoc=None):
        if homepage is None and capdoc is not None:
            homepage = capdoc['links']['homepage']
        if token_url is None and capdoc is not None:
            token_url = capdoc['capabilities']['oauth2Provider']['tokenUrl']
        if capabilities_url is None and capdoc is not None:
            capabilities_url = capdoc['links']['self']
        if capdoc is not None:
            api_base_url = capdoc['capabilities']['hipchatApiProvider']['url']
        else:
            api_base_url = capabilities_url.rsplit('/', 1)[0]
        installed_from = token_url and base_url(token_url) or None

        return BaseManager.create(
            self,
            id=id,
            room_id=room_id,
            secret=secret,
            homepage=homepage,
            token_url=token_url,
            capabilities_url=capabilities_url,
            api_base_url=api_base_url,
            installed_from=installed_from,
        )
Exemplo n.º 6
0
class GroupEmailThread(Model):
    """
    Keep track of the original Message-Id that was sent
    unique per email destination and Group object.This allows
    the tracking of proper In-Reply-To and References headers
    for email threading.
    """

    __include_in_export__ = False

    email = models.EmailField(max_length=75)
    project = FlexibleForeignKey("sentry.Project",
                                 related_name="groupemail_set")
    group = FlexibleForeignKey("sentry.Group", related_name="groupemail_set")
    msgid = models.CharField(max_length=100)
    date = models.DateTimeField(default=timezone.now, db_index=True)

    objects = BaseManager()

    class Meta:
        app_label = "sentry"
        db_table = "sentry_groupemailthread"
        unique_together = (("email", "group"), ("email", "msgid"))
        indexes = [models.Index(fields=["date", "project", "id"])]

    __repr__ = sane_repr("email", "group_id", "msgid")
Exemplo n.º 7
0
class ServiceHook(Model):
    __include_in_export__ = True

    guid = models.CharField(max_length=32, unique=True, null=True)
    # hooks may be bound to an api application, or simply registered by a user
    application = FlexibleForeignKey("sentry.ApiApplication", null=True)
    actor_id = BoundedPositiveIntegerField(db_index=True)
    project_id = BoundedPositiveIntegerField(db_index=True, null=True)
    organization_id = BoundedPositiveIntegerField(db_index=True, null=True)
    url = models.URLField(max_length=512)
    secret = EncryptedTextField(default=generate_secret)
    events = ArrayField(of=models.TextField)
    status = BoundedPositiveIntegerField(default=0,
                                         choices=ObjectStatus.as_choices(),
                                         db_index=True)
    version = BoundedPositiveIntegerField(default=0, choices=((0, "0"), ))
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager(cache_fields=("guid", ))

    class Meta:
        app_label = "sentry"
        db_table = "sentry_servicehook"

    __repr__ = sane_repr("guid", "project_id")

    @property
    def created_by_sentry_app(self):
        return self.application_id and self.sentry_app

    @property
    def sentry_app(self):
        try:
            return SentryApp.objects.get(application_id=self.application_id)
        except SentryApp.DoesNotExist:
            return

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.guid is None:
            self.guid = uuid4().hex

    def __str__(self):
        return str(self.guid)

    def build_signature(self, body):
        return hmac.new(key=self.secret.encode("utf-8"),
                        msg=body.encode("utf-8"),
                        digestmod=sha256).hexdigest()

    def get_audit_log_data(self):
        return {"url": self.url}

    def add_project(self, project):
        """
        Add a project to the service hook.

        """
        ServiceHookProject.objects.create(project_id=project.id,
                                          service_hook_id=self.id)
Exemplo n.º 8
0
class AccessGroup(Model):
    """
    An access group identifies a set of members with a defined set
    of permissions (and project access) for a Team.

    Groups may be automated through extensions (such as LDAP) so that
    membership is automatically maintained. If this is the case the
    ``managed`` attribute will be ``True``.
    """
    team = models.ForeignKey('sentry.Team')
    name = models.CharField(max_length=64)
    type = BoundedIntegerField(choices=MEMBER_TYPES, default=MEMBER_USER)
    managed = models.BooleanField(default=False)
    data = GzippedDictField(blank=True, null=True)
    date_added = models.DateTimeField(default=timezone.now)

    projects = models.ManyToManyField('sentry.Project')
    members = models.ManyToManyField(settings.AUTH_USER_MODEL)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_accessgroup'
        unique_together = (('team', 'name'),)

    __repr__ = sane_repr('team_id', 'name', 'type', 'managed')
Exemplo n.º 9
0
class MonitorCheckIn(Model):
    __core__ = False

    guid = UUIDField(unique=True, auto_add=True)
    project_id = BoundedPositiveIntegerField(db_index=True)
    monitor = FlexibleForeignKey("sentry.Monitor")
    location = FlexibleForeignKey("sentry.MonitorLocation", null=True)
    status = BoundedPositiveIntegerField(default=0,
                                         choices=CheckInStatus.as_choices())
    config = EncryptedJsonField(default=dict)
    duration = BoundedPositiveIntegerField(null=True)
    date_added = models.DateTimeField(default=timezone.now)
    date_updated = models.DateTimeField(default=timezone.now)
    objects = BaseManager(cache_fields=("guid", ))

    class Meta:
        app_label = "sentry"
        db_table = "sentry_monitorcheckin"

    __repr__ = sane_repr("guid", "project_id", "status")

    def save(self, *args, **kwargs):
        if not self.date_added:
            self.date_added = timezone.now()
        if not self.date_updated:
            self.date_updated = self.date_added
        return super(MonitorCheckIn, self).save(*args, **kwargs)

    # XXX(dcramer): BaseModel is trying to automatically set date_updated which is not
    # what we want to happen, so kill it here
    def _update_timestamps(self):
        pass
Exemplo n.º 10
0
class TagValue(Model):
    """
    Stores references to available filters.
    """
    __core__ = False

    project_id = BoundedPositiveIntegerField(db_index=True, null=True)
    key = models.CharField(max_length=MAX_TAG_KEY_LENGTH)
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    data = GzippedDictField(blank=True, null=True)
    times_seen = BoundedPositiveIntegerField(default=0)
    last_seen = models.DateTimeField(default=timezone.now,
                                     db_index=True,
                                     null=True)
    first_seen = models.DateTimeField(default=timezone.now,
                                      db_index=True,
                                      null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_filtervalue'
        unique_together = (('project_id', 'key', 'value'), )

    __repr__ = sane_repr('project_id', 'key', 'value')

    def get_label(self):
        # HACK(dcramer): quick and dirty way to hack in better display states
        if self.key == 'sentry:release':
            return Release.get_display_version(self.value)
        return self.value
Exemplo n.º 11
0
class GroupTagKey(Model):
    """
    Stores a unique tag key name for a group.

    An example key might be "url" or "server_name".
    """

    __core__ = False

    project_id = BoundedPositiveIntegerField(db_index=True, null=True)
    group_id = BoundedPositiveIntegerField(db_index=True)
    key = models.CharField(max_length=MAX_TAG_KEY_LENGTH)
    values_seen = BoundedPositiveIntegerField(default=0)

    objects = BaseManager()

    class Meta:
        app_label = "sentry"
        db_table = "sentry_grouptagkey"
        unique_together = (("project_id", "group_id", "key"), )

    __repr__ = sane_repr("project_id", "group_id", "key")

    def merge_counts(self, new_group):
        from sentry.tagstore.legacy.models import GroupTagValue

        try:
            with transaction.atomic(using=router.db_for_write(GroupTagKey)):
                GroupTagKey.objects.filter(
                    group_id=new_group.id, key=self.key).update(
                        values_seen=GroupTagValue.objects.filter(
                            group_id=new_group.id, key=self.key).count())
        except DataError:
            # it's possible to hit an out of range value for counters
            pass
Exemplo n.º 12
0
class TeamMember(Model):
    """
    Identifies relationships between teams and users.

    Users listed as team members are considered to have access to all projects
    and could be thought of as team owners (though their access level may not)
    be set to ownership.
    """
    team = FlexibleForeignKey('sentry.Team', related_name=None)
    user = FlexibleForeignKey(settings.AUTH_USER_MODEL, related_name=None)
    type = BoundedIntegerField(choices=(
        (TeamMemberType.MEMBER, _('Member')),
        (TeamMemberType.ADMIN, _('Admin')),
        (TeamMemberType.BOT, _('Bot')),
    ),
                               default=TeamMemberType.MEMBER)
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_teammember'
        unique_together = (('team', 'user'), )

    __repr__ = sane_repr('team_id', 'user_id', 'type')
Exemplo n.º 13
0
class UserAvatar(AvatarBase):
    """
    A UserAvatar associates a User with their avatar photo File
    and contains their preferences for avatar type.
    """

    AVATAR_TYPES = (
        (0, 'letter_avatar'),
        (1, 'upload'),
        (2, 'gravatar'),
    )

    FILE_TYPE = 'avatar.file'

    user = FlexibleForeignKey('sentry.User', unique=True, related_name='avatar')
    avatar_type = models.PositiveSmallIntegerField(default=0, choices=AVATAR_TYPES)

    objects = BaseManager(cache_fields=['user'])

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_useravatar'

    def get_cache_key(self, size):
        return 'avatar:%s:%s' % (self.user_id, size)
Exemplo n.º 14
0
class TagValue(Model):
    """
    Stores references to available filters.
    """
    __core__ = False

    project_id = BoundedPositiveIntegerField(db_index=True)
    environment_id = BoundedPositiveIntegerField(null=True)
    _key = FlexibleForeignKey('tagstore.TagKey', db_column='key')
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    data = GzippedDictField(blank=True, null=True)
    times_seen = BoundedPositiveIntegerField(default=0)
    last_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)
    first_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'tagstore'
        unique_together = (('project_id', 'environment_id', '_key', 'value'), )
        # TODO: environment index(es)
        index_together = (('project_id', '_key', 'last_seen'), )

    __repr__ = sane_repr('project_id', 'environment_id', '_key', 'value')

    @property
    def key(self):
        return self._key.key

    def get_label(self):
        from sentry import tagstore

        return tagstore.get_tag_value_label(self.key, self.value)
Exemplo n.º 15
0
class TagValue(Model):
    """
    Stores references to available filters.
    """
    __core__ = False

    project = FlexibleForeignKey('sentry.Project', null=True)
    key = models.CharField(max_length=MAX_TAG_KEY_LENGTH)
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    data = GzippedDictField(blank=True, null=True)
    times_seen = BoundedPositiveIntegerField(default=0)
    last_seen = models.DateTimeField(default=timezone.now,
                                     db_index=True,
                                     null=True)
    first_seen = models.DateTimeField(default=timezone.now,
                                      db_index=True,
                                      null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_filtervalue'
        unique_together = (('project', 'key', 'value'), )

    __repr__ = sane_repr('project_id', 'key', 'value')

    def get_label(self):
        # HACK(dcramer): quick and dirty way to hack in better display states
        if self.key == 'sentry:user':
            return self.data.get('email') or self.value
        elif self.key == 'sentry:function':
            return '%s in %s' % (self.data['function'], self.data['filename'])
        elif self.key == 'sentry:filename':
            return self.data['filename']
        return self.value

    def get_absolute_url(self):
        # HACK(dcramer): quick and dirty way to support code/users
        if self.key == 'sentry:user':
            url_name = 'sentry-user-details'
        elif self.key == 'sentry:filename':
            url_name = 'sentry-explore-code-details'
        elif self.key == 'sentry:function':
            url_name = 'sentry-explore-code-details-by-function'
        else:
            url_name = 'sentry-explore-tag-value'
            return absolute_uri(
                reverse(url_name,
                        args=[
                            self.project.organization.slug, self.project.slug,
                            self.key, self.id
                        ]))

        return absolute_uri(
            reverse(url_name,
                    args=[
                        self.project.organization.slug, self.project.slug,
                        self.id
                    ]))
Exemplo n.º 16
0
class ApiKey(Model):
    organization = FlexibleForeignKey('sentry.Organization',
                                      related_name='key_set')
    label = models.CharField(max_length=64, blank=True, default='Default')
    key = models.CharField(max_length=32, unique=True)
    scopes = BitField(flags=(
        ('project:read', 'project:read'),
        ('project:write', 'project:write'),
        ('project:delete', 'project:delete'),
        ('team:read', 'team:read'),
        ('team:write', 'team:write'),
        ('team:delete', 'team:delete'),
        ('event:read', 'event:read'),
        ('event:write', 'event:write'),
        ('event:delete', 'event:delete'),
        ('org:read', 'org:read'),
        ('org:write', 'org:write'),
        ('org:delete', 'org:delete'),
    ))
    status = BoundedPositiveIntegerField(default=0,
                                         choices=(
                                             (ApiKeyStatus.ACTIVE,
                                              _('Active')),
                                             (ApiKeyStatus.INACTIVE,
                                              _('Inactive')),
                                         ),
                                         db_index=True)
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager(cache_fields=('key', ))

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_apikey'

    __repr__ = sane_repr('organization_id', 'key')

    def __unicode__(self):
        return six.text_type(self.key)

    @classmethod
    def generate_api_key(cls):
        return uuid4().hex

    @property
    def is_active(self):
        return self.status == ApiKeyStatus.ACTIVE

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = ApiKey.generate_api_key()
        super(ApiKey, self).save(*args, **kwargs)

    def get_audit_log_data(self):
        return {
            'label': self.label,
            'key': self.key,
            'roles': int(self.roles),
            'status': self.status,
        }
Exemplo n.º 17
0
class GroupEmailThread(Model):
    """
    Keep track of the original Message-Id that was sent
    unique per email destination and Group object.This allows
    the tracking of proper In-Reply-To and References headers
    for email threading.
    """
    __core__ = False

    email = models.EmailField(max_length=75)
    project = FlexibleForeignKey('sentry.Project',
                                 related_name="groupemail_set")
    group = FlexibleForeignKey('sentry.Group', related_name="groupemail_set")
    msgid = models.CharField(max_length=100)
    date = models.DateTimeField(default=timezone.now, db_index=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_groupemailthread'
        unique_together = (
            ('email', 'group'),
            ('email', 'msgid'),
        )

    __repr__ = sane_repr('email', 'group_id', 'msgid')
Exemplo n.º 18
0
class ProjectBookmark(Model):
    """
    Identifies a bookmark relationship between a user and an
    aggregated event (Group).
    """
    __core__ = True

    project = FlexibleForeignKey(Project,
                                 blank=True,
                                 null=True,
                                 db_constraint=False)
    user = FlexibleForeignKey(settings.AUTH_USER_MODEL)
    date_added = models.DateTimeField(default=timezone.now, null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_projectbookmark'
        unique_together = ((
            'project',
            'user',
        ))

    __repr__ = sane_repr('project_id', 'user_id')
Exemplo n.º 19
0
class ApiToken(Model):
    # users can generate tokens without being key-bound
    key = FlexibleForeignKey('sentry.ApiKey', null=True)
    user = FlexibleForeignKey('sentry.User')
    token = models.CharField(max_length=64, unique=True)
    scopes = BitField(flags=(
        ('project:read', 'project:read'),
        ('project:write', 'project:write'),
        ('project:delete', 'project:delete'),
        ('team:read', 'team:read'),
        ('team:write', 'team:write'),
        ('team:delete', 'team:delete'),
        ('event:read', 'event:read'),
        ('event:write', 'event:write'),
        ('event:delete', 'event:delete'),
        ('org:read', 'org:read'),
        ('org:write', 'org:write'),
        ('org:delete', 'org:delete'),
        ('member:read', 'member:read'),
        ('member:write', 'member:write'),
        ('member:delete', 'member:delete'),
    ))
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager(cache_fields=('token', ))

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_apitoken'

    __repr__ = sane_repr('key_id', 'user_id', 'token')

    def __unicode__(self):
        return six.text_type(self.token)

    @classmethod
    def generate_token(cls):
        return uuid4().hex + uuid4().hex

    def save(self, *args, **kwargs):
        if not self.token:
            self.token = type(self).generate_token()
        super(ApiToken, self).save(*args, **kwargs)

    def get_audit_log_data(self):
        return {
            'scopes': int(self.scopes),
        }

    def get_scopes(self):
        return [k for k, v in self.scopes.iteritems() if v]

    def has_scope(self, scope):
        return scope in self.scopes

    def get_allowed_origins(self):
        if self.key:
            return self.key.get_allowed_origins()
        return ()
Exemplo n.º 20
0
class GroupTagValue(Model):
    """
    Stores the total number of messages seen by a group matching
    the given filter.
    """
    project = FlexibleForeignKey('sentry.Project',
                                 null=True,
                                 related_name='grouptag')
    group = FlexibleForeignKey('sentry.Group', related_name='grouptag')
    times_seen = BoundedPositiveIntegerField(default=0)
    key = models.CharField(max_length=MAX_TAG_KEY_LENGTH)
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    last_seen = models.DateTimeField(default=timezone.now,
                                     db_index=True,
                                     null=True)
    first_seen = models.DateTimeField(default=timezone.now,
                                      db_index=True,
                                      null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_messagefiltervalue'
        unique_together = (('project', 'key', 'value', 'group'), )

    __repr__ = sane_repr('project_id', 'group_id', 'key', 'value')

    def save(self, *args, **kwargs):
        if not self.first_seen:
            self.first_seen = self.last_seen
        super(GroupTag, self).save(*args, **kwargs)

    @classmethod
    def get_value_count(cls, group_id, key):
        if db.is_postgres():
            # This doesnt guarantee percentage is accurate, but it does ensure
            # that the query has a maximum cost
            cursor = connections['default'].cursor()
            cursor.execute(
                """
                SELECT SUM(t)
                FROM (
                    SELECT times_seen as t
                    FROM sentry_messagefiltervalue
                    WHERE group_id = %s
                    AND key = %s
                    AND last_seen > NOW() - INTERVAL '7 days'
                    LIMIT 10000
                ) as a
            """, [group_id, key])
            return cursor.fetchone()[0] or 0

        cutoff = timezone.now() - timedelta(days=7)
        return cls.objects.filter(
            group=group_id,
            key=key,
            last_seen__gte=cutoff,
        ).aggregate(t=Sum('times_seen'))['t']
Exemplo n.º 21
0
class GroupTagValue(Model):
    """
    Stores the total number of messages seen by a group matching
    the given filter.
    """
    __core__ = False

    project_id = BoundedPositiveIntegerField(db_index=True)
    group_id = BoundedPositiveIntegerField(db_index=True)
    environment_id = BoundedPositiveIntegerField(null=True)
    times_seen = BoundedPositiveIntegerField(default=0)
    _key = FlexibleForeignKey('tagstore.TagKey', db_column='key_id')
    _value = FlexibleForeignKey('tagstore.TagValue', db_column='value_id')
    last_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)
    first_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'tagstore'
        unique_together = (('project_id', 'group_id', 'environment_id', '_key', '_value'), )
        index_together = (('project_id', '_key', '_value', 'last_seen'), )

    __repr__ = sane_repr('project_id', 'group_id', '_key', '_value')

    @property
    def key(self):
        return self._key.key

    @property
    def value(self):
        return self._value.value

    def save(self, *args, **kwargs):
        if not self.first_seen:
            self.first_seen = self.last_seen
        super(GroupTagValue, self).save(*args, **kwargs)

    def merge_counts(self, new_group):
        try:
            with transaction.atomic(using=router.db_for_write(GroupTagValue)):
                new_obj = GroupTagValue.objects.get(
                    group_id=new_group.id,
                    environment_id=self.environment_id,
                    _key_id=self._key_id,
                    _value_id=self._value_id,
                )
                new_obj.update(
                    first_seen=min(new_obj.first_seen, self.first_seen),
                    last_seen=max(new_obj.last_seen, self.last_seen),
                    times_seen=new_obj.times_seen + self.times_seen,
                )
        except DataError:
            # it's possible to hit an out of range value for counters
            pass
Exemplo n.º 22
0
class GroupTagValue(Model):
    """
    Stores the total number of messages seen by a group matching
    the given filter.
    """
    __core__ = False

    project_id = BoundedPositiveIntegerField(db_index=True)
    group_id = BoundedPositiveIntegerField(db_index=True)
    environment_id = BoundedPositiveIntegerField()
    # times_seen will live in Redis
    key_id = BoundedPositiveIntegerField()
    value_id = BoundedPositiveIntegerField()
    last_seen = models.DateTimeField(default=timezone.now,
                                     db_index=True,
                                     null=True)
    first_seen = models.DateTimeField(default=timezone.now,
                                      db_index=True,
                                      null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'tagstore'
        unique_together = (('project_id', 'group_id', 'environment_id',
                            'key_id', 'value_id'), )
        # TODO: environment index(es)
        index_together = (('project_id', 'key_id', 'value_id', 'last_seen'), )

    __repr__ = sane_repr('project_id', 'group_id', 'key_id', 'value_id')

    # TODO: key property to fetch actual key string?
    # TODO: value property to fetch actual value string?

    def save(self, *args, **kwargs):
        if not self.first_seen:
            self.first_seen = self.last_seen
        super(GroupTagValue, self).save(*args, **kwargs)

    # TODO: this will have to iterate all of the possible environments a group has?
    # TODO: times_seen will live in Redis
    def merge_counts(self, new_group):
        try:
            with transaction.atomic(using=router.db_for_write(GroupTagValue)):
                new_obj = GroupTagValue.objects.get(
                    group_id=new_group.id,
                    key_id=self.key_id,
                    value_id=self.value_id,
                )
                new_obj.update(
                    first_seen=min(new_obj.first_seen, self.first_seen),
                    last_seen=max(new_obj.last_seen, self.last_seen),
                    times_seen=new_obj.times_seen + self.times_seen,
                )
        except DataError:
            # it's possible to hit an out of range value for counters
            pass
Exemplo n.º 23
0
class ParanoidModel(Model):
    class Meta:
        abstract = True

    date_deleted = models.DateTimeField(null=True, blank=True)
    objects = ParanoidManager()
    with_deleted = BaseManager()

    def delete(self):
        self.update(date_deleted=timezone.now())
Exemplo n.º 24
0
class ApiToken(Model, HasApiScopes):
    __core__ = True

    # users can generate tokens without being application-bound
    application = FlexibleForeignKey("sentry.ApiApplication", null=True)
    user = FlexibleForeignKey("sentry.User")
    token = models.CharField(max_length=64,
                             unique=True,
                             default=generate_token)
    refresh_token = models.CharField(max_length=64,
                                     unique=True,
                                     null=True,
                                     default=generate_token)
    expires_at = models.DateTimeField(null=True, default=default_expiration)
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager(cache_fields=("token", ))

    class Meta:
        app_label = "sentry"
        db_table = "sentry_apitoken"

    __repr__ = sane_repr("user_id", "token", "application_id")

    def __str__(self):
        return force_text(self.token)

    @classmethod
    def from_grant(cls, grant):
        with transaction.atomic():
            return cls.objects.create(application=grant.application,
                                      user=grant.user,
                                      scope_list=grant.get_scopes())

    def is_expired(self):
        if not self.expires_at:
            return False

        return timezone.now() >= self.expires_at

    def get_audit_log_data(self):
        return {"scopes": self.get_scopes()}

    def get_allowed_origins(self):
        if self.application:
            return self.application.get_allowed_origins()
        return ()

    def refresh(self, expires_at=None):
        if expires_at is None:
            expires_at = timezone.now() + DEFAULT_EXPIRATION

        self.update(token=generate_token(),
                    refresh_token=generate_token(),
                    expires_at=expires_at)
Exemplo n.º 25
0
class ServiceHook(Model):
    __core__ = True

    guid = models.CharField(max_length=32, unique=True, null=True)
    # hooks may be bound to an api application, or simply registered by a user
    application = FlexibleForeignKey('sentry.ApiApplication', null=True)
    actor_id = BoundedPositiveIntegerField(db_index=True)
    project_id = BoundedPositiveIntegerField(db_index=True)
    organization_id = BoundedPositiveIntegerField(db_index=True, null=True)
    url = models.URLField(max_length=512)
    secret = EncryptedTextField(default=generate_secret)
    events = ArrayField(of=models.TextField)
    status = BoundedPositiveIntegerField(default=0,
                                         choices=ObjectStatus.as_choices(),
                                         db_index=True)
    version = BoundedPositiveIntegerField(default=0, choices=((0, '0'), ))
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager(cache_fields=('guid', ))

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_servicehook'

    __repr__ = sane_repr('guid', 'project_id')

    @property
    def created_by_sentry_app(self):
        return (self.application_id and self.sentry_app)

    @property
    def sentry_app(self):
        try:
            return SentryApp.objects.get(application_id=self.application_id)
        except SentryApp.DoesNotExist:
            return

    def __init__(self, *args, **kwargs):
        super(ServiceHook, self).__init__(*args, **kwargs)
        if self.guid is None:
            self.guid = uuid4().hex

    def __unicode__(self):
        return six.text_type(self.guid)

    def build_signature(self, body):
        return hmac.new(
            key=self.secret.encode('utf-8'),
            msg=body.encode('utf-8'),
            digestmod=sha256,
        ).hexdigest()

    def get_audit_log_data(self):
        return {'url': self.url}
Exemplo n.º 26
0
class TagValue(Model):
    """
    Stores references to available filters.
    """
    __core__ = False

    project_id = BoundedBigIntegerField(db_index=True)
    _key = FlexibleForeignKey('tagstore.TagKey', db_column='key_id')
    value = models.CharField(max_length=MAX_TAG_VALUE_LENGTH)
    data = GzippedDictField(blank=True, null=True)
    times_seen = BoundedPositiveIntegerField(default=0)
    last_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)
    first_seen = models.DateTimeField(
        default=timezone.now, db_index=True, null=True)

    objects = BaseManager()

    class Meta:
        app_label = 'tagstore'
        unique_together = (('project_id', '_key', 'value'), )
        index_together = (('project_id', '_key', 'last_seen'), )

    __repr__ = sane_repr('project_id', '_key', 'value')

    @property
    def key(self):
        if hasattr(self, '_set_key'):
            return self._set_key

        if hasattr(self, '__key_cache'):
            return self._key.key

        # fallback
        from sentry.tagstore.v2.models import TagKey

        tk = TagKey.objects.filter(
            project_id=self.project_id,
            id=self._key_id,
        ).values_list('key', flat=True).get()

        # cache for future calls
        self.key = tk

        return tk

    @key.setter
    def key(self, key):
        self._set_key = key

    def get_label(self):
        from sentry import tagstore

        return tagstore.get_tag_value_label(self.key, self.value)
Exemplo n.º 27
0
class PendingTeamMember(Model):
    """
    Identifies relationships between teams and pending invites.
    """
    team = FlexibleForeignKey('sentry.Team', related_name="pending_member_set")
    email = models.EmailField()
    type = BoundedIntegerField(choices=MEMBER_TYPES, default=MEMBER_USER)
    date_added = models.DateTimeField(default=timezone.now)

    objects = BaseManager()

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_pendingteammember'
        unique_together = (('team', 'email'), )

    __repr__ = sane_repr('team_id', 'email', 'type')

    @property
    def token(self):
        checksum = md5()
        for x in (str(self.team_id), self.email, settings.SECRET_KEY):
            checksum.update(x)
        return checksum.hexdigest()

    def send_invite_email(self):
        from sentry.utils.email import MessageBuilder

        context = {
            'email':
            self.email,
            'team':
            self.team,
            'url':
            absolute_uri(
                reverse('sentry-accept-invite',
                        kwargs={
                            'member_id': self.id,
                            'token': self.token,
                        })),
        }

        msg = MessageBuilder(
            subject='Invite to join team: %s' % (self.team.name, ),
            template='sentry/emails/member_invite.txt',
            context=context,
        )

        try:
            msg.send([self.email])
        except Exception as e:
            logger = logging.getLogger('sentry.mail.errors')
            logger.exception(e)
Exemplo n.º 28
0
class MonitorLocation(Model):
    __core__ = True

    guid = UUIDField(unique=True, auto_add=True)
    name = models.CharField(max_length=128)
    date_added = models.DateTimeField(default=timezone.now)
    objects = BaseManager(cache_fields=('guid', ))

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_monitorlocation'

    __repr__ = sane_repr('guid', 'name')
Exemplo n.º 29
0
class MonitorLocation(Model):
    __include_in_export__ = True

    guid = UUIDField(unique=True, auto_add=True)
    name = models.CharField(max_length=128)
    date_added = models.DateTimeField(default=timezone.now)
    objects = BaseManager(cache_fields=("guid", ))

    class Meta:
        app_label = "sentry"
        db_table = "sentry_monitorlocation"

    __repr__ = sane_repr("guid", "name")
Exemplo n.º 30
0
class GroupTagKey(Model):
    """
    Stores a unique tag key name for a group.

    An example key might be "url" or "server_name".
    """
    __core__ = False

    project_id = BoundedBigIntegerField(db_index=True)
    group_id = BoundedBigIntegerField(db_index=True)
    _key = FlexibleForeignKey('tagstore.TagKey', db_column='key_id')
    values_seen = BoundedPositiveIntegerField(default=0)

    objects = BaseManager()

    class Meta:
        app_label = 'tagstore'
        unique_together = (('project_id', 'group_id', '_key'), )

    __repr__ = sane_repr('project_id', 'group_id', '_key')

    @property
    def key(self):
        if hasattr(self, '_set_key'):
            return self._set_key

        return self._key.key

    @key.setter
    def key(self, key):
        self._set_key = key

    @staticmethod
    def get_select_related_for_merge():
        return ('_key', )

    def merge_counts(self, new_group):
        from sentry.tagstore.v2.models import GroupTagValue

        try:
            with transaction.atomic(using=router.db_for_write(GroupTagKey)):
                GroupTagKey.objects.filter(
                    group_id=new_group.id,
                    _key_id=self._key_id,
                ).update(values_seen=GroupTagValue.objects.filter(
                    group_id=new_group.id,
                    _key_id=self._key_id,
                ).count())
        except DataError:
            # it's possible to hit an out of range value for counters
            pass
Exemplo n.º 31
0
class VersionDSymFile(Model):
    __core__ = False

    objects = BaseManager()
    dsym_file = FlexibleForeignKey('sentry.ProjectDSymFile', null=True)
    dsym_app = FlexibleForeignKey('sentry.DSymApp')
    version = models.CharField(max_length=32)
    build = models.CharField(max_length=32, null=True)
    date_added = models.DateTimeField(default=timezone.now)

    class Meta:
        app_label = 'sentry'
        db_table = 'sentry_versiondsymfile'
        unique_together = (('dsym_file', 'version', 'build'), )
Exemplo n.º 32
0
    def create_or_update_app(
        self, sync_id, app_id, project, data=None, platform=DSymPlatform.GENERIC,
        no_fetch=False
    ):
        if data is None:
            data = {}
        if not no_fetch:
            _auto_enrich_data(data, app_id, platform)
        existing_app = DSymApp.objects.filter(app_id=app_id, project=project).first()
        if existing_app is not None:
            now = timezone.now()
            existing_app.update(
                sync_id=sync_id,
                data=data,
                last_synced=now,
            )
            return existing_app

        return BaseManager.create(
            self, sync_id=sync_id, app_id=app_id, data=data, project=project, platform=platform
        )