Пример #1
0
class RolePermission(models.Model):
    role = models.ForeignKey("UserRole", on_delete=models.CASCADE)
    permission_fk = models.ForeignKey("SQLPermission", on_delete=models.CASCADE)
    permission = ForeignValue(permission_fk)

    # if True allow access to all items
    # if False only allow access to listed items
    allow_all = models.BooleanField(default=True)

    # current max len in 119 chars
    allowed_items = ArrayField(models.CharField(max_length=256), blank=True, null=True)

    class Meta:
        unique_together = [
            ("role", "permission_fk")
        ]
        constraints = [
            models.CheckConstraint(
                name="users_rolepermission_valid_allow",
                check=~models.Q(allow_all=True, allowed_items__len__gt=0)
            ),
        ]

    @staticmethod
    def from_permission_info(role, info):
        return RolePermission(
            role=role, permission=info.name, allow_all=info.allow_all, allowed_items=info.allowed_items
        )

    def as_permission_info(self):
        from corehq.apps.users.models import PermissionInfo
        allow = PermissionInfo.ALLOW_ALL if self.allow_all else self.allowed_items
        return PermissionInfo(self.permission, allow=allow)
Пример #2
0
class NavigationEventAudit(AuditEvent):
    """
    Audit event to track happenings within the system, ie, view access
    """
    params = TruncatingCharField(max_length=4096, blank=True, default='')
    view_fk = models.ForeignKey(
        ViewName, null=True, db_index=False, on_delete=models.PROTECT)
    view = ForeignValue(view_fk, truncate=True)
    view_kwargs = NullJsonField(default=dict)
    headers = NullJsonField(default=dict)
    status_code = models.SmallIntegerField(default=0)

    @property
    def description(self):
        return self.user or ""

    @property
    def request_path(self):
        return f"{self.path}?{self.params}"

    @classmethod
    def audit_view(cls, request, user, view_func, view_kwargs):
        audit = cls.create_audit(request, user)
        if request.GET:
            audit.params = request.META.get("QUERY_STRING", "")
        audit.view = "%s.%s" % (view_func.__module__, view_func.__name__)
        for k in STANDARD_HEADER_KEYS:
            header_item = request.META.get(k, None)
            if header_item is not None:
                audit.headers[k] = header_item
        # it's a bit verbose to go to that extreme, TODO: need to have
        # targeted fields in the META, but due to server differences, it's
        # hard to make it universal.
        audit.view_kwargs = view_kwargs
        return audit
Пример #3
0
class AuditEvent(models.Model):
    id = models.BigAutoField(primary_key=True)
    user = models.CharField(max_length=255, null=True, blank=True)
    domain = models.CharField(max_length=126, null=True, blank=True)
    event_date = models.DateTimeField(default=getdate, db_index=True)
    path = TruncatingCharField(max_length=255, blank=True, default='')
    ip_address = models.CharField(max_length=45, blank=True, default='')
    session_key = models.CharField(max_length=255, blank=True, null=True)
    user_agent_fk = models.ForeignKey(UserAgent,
                                      null=True,
                                      db_index=False,
                                      on_delete=models.PROTECT)
    user_agent = ForeignValue(user_agent_fk, truncate=True)
    couch_id = models.CharField(max_length=126, null=True)

    @property
    def doc_type(self):
        return type(self).__name__

    @property
    def description(self):
        raise NotImplementedError("abstract property")

    class Meta:
        abstract = True
        indexes = [
            models.Index(fields=["user", "event_date"]),
            models.Index(fields=["domain", "event_date"]),
        ]

    def __str__(self):
        return "[%s] %s" % (self.doc_type, self.description)

    @classmethod
    def create_audit(cls, request, user):
        audit = cls()
        audit.domain = get_domain(request)
        audit.path = request.path
        audit.ip_address = get_ip(request)
        audit.session_key = request.session.session_key
        audit.user_agent = request.META.get('HTTP_USER_AGENT')
        if isinstance(user, AnonymousUser):
            audit.user = None
        elif user is None:
            audit.user = None
        elif isinstance(user, User):
            audit.user = user.username
        else:
            audit.user = user
        return audit
Пример #4
0
class AccessAudit(AuditEvent):
    access_type = models.CharField(max_length=1,
                                   choices=ACCESS_CHOICES.items())
    http_accept_fk = models.ForeignKey(HttpAccept,
                                       null=True,
                                       db_index=False,
                                       on_delete=models.PROTECT)
    http_accept = ForeignValue(http_accept_fk, truncate=True)
    trace_id = models.CharField(max_length=127, null=True, blank=True)

    class Meta(AuditEvent.Meta):
        constraints = [
            models.UniqueConstraint(fields=['couch_id'],
                                    condition=models.Q(couch_id__isnull=False),
                                    name="audit_access_couch_10d1b_idx"),
        ]

    # Optional (django-ified) settings.AUDIT_TRACE_ID_HEADER set by AuditcareConfig
    trace_id_header = None

    @property
    def description(self):
        return f"{ACCESS_CHOICES[self.access_type]}: {self.user or ''}"

    @classmethod
    def create_audit(cls, request, user, access_type):
        '''Creates an instance of a Access log.'''
        audit = super().create_audit(request, user)
        audit.http_accept = request.META.get('HTTP_ACCEPT')
        audit.access_type = access_type
        if cls.trace_id_header is not None:
            audit.trace_id = request.META.get(cls.trace_id_header)
        return audit

    @classmethod
    def audit_login(cls, request, user, *args, **kwargs):
        audit = cls.create_audit(request, user, ACCESS_LOGIN)
        audit.save()

    @classmethod
    def audit_login_failed(cls, request, username, *args, **kwargs):
        audit = cls.create_audit(request, username, ACCESS_FAILED)
        audit.save()

    @classmethod
    def audit_logout(cls, request, user):
        audit = cls.create_audit(request, user, ACCESS_LOGOUT)
        audit.save()
Пример #5
0
class UserAccessLog(models.Model):
    TYPE_LOGIN = '******'
    TYPE_LOGOUT = 'logout'
    TYPE_FAILURE = 'failure'

    ACTIONS = ((TYPE_LOGIN, 'Login'), (TYPE_LOGOUT, 'Logout'),
               (TYPE_FAILURE, 'Login Failure'))

    id = models.BigAutoField(primary_key=True)
    user_id = models.CharField(max_length=255, db_index=True)
    action = models.CharField(max_length=20, choices=ACTIONS)
    ip = models.GenericIPAddressField(blank=True, null=True)
    user_agent_fk = models.ForeignKey(UserAgent,
                                      null=True,
                                      on_delete=models.PROTECT,
                                      db_column="user_agent_id")
    user_agent = ForeignValue(user_agent_fk, truncate=True)
    path = models.CharField(max_length=255, blank=True)
    timestamp = models.DateTimeField(default=datetime.utcnow)

    def __str__(self):
        return f'{self.timestamp}: {self.user_id} - {self.action}'
Пример #6
0
def get_foreign_names(model):
    names = {f.name for f in model._meta.fields if isinstance(f, ForeignKey)}
    names.update(ForeignValue.get_names(model))
    return names