# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import threading
from datetime import datetime
from time import time
from django.db import models
from django.utils.translation import ugettext_lazy as _
from networkapi.queue_tools.rabbitmq import QueueManager
LOG = logging.getLogger(__name__)
[docs]class EventLogError(Exception):
"""Representa um erro ocorrido durante acesso à tabela event_log."""
def __init__(self, cause, message=None):
self.cause = cause
self.message = message
def __str__(self):
msg = u'Causa: %s, Mensagem: %s' % (self.cause, self.message)
return msg.encode('utf-8', 'replace')
[docs]class EventLog(models.Model):
ADD = 0
CHANGE = 1
DELETE = 2
id = models.AutoField(primary_key=True, db_column='id_evento')
usuario = models.ForeignKey(
'usuario.Usuario',
db_column='id_user',
blank=True,
null=True
)
hora_evento = models.DateTimeField()
acao = models.TextField()
funcionalidade = models.TextField()
parametro_anterior = models.TextField()
parametro_atual = models.TextField()
evento = models.TextField()
resultado = models.IntegerField()
id_objeto = models.IntegerField()
audit_request = models.ForeignKey(
'eventlog.AuditRequest',
db_column='id_audit_request',
blank=True,
null=True
)
logger = logging.getLogger('EventLog')
class Meta:
db_table = u'event_log'
managed = True
[docs] @classmethod
def log(cls, usuario, evento):
"""
saves the eventlog in the database
@params
usuario: Usuario object
evento: dict in the form
{
"acao": value,
"funcionalidade": value,
"parametro_anterior": value,
"parametro_atual": value,
"id_objeto": value,
"audit_request": value
}
"""
parametro_anterior = [
'{0} : {1}'.format(key, evento['parametro_anterior'][key])
for key in evento['parametro_anterior']]
parametro_anterior = u'\n'.join(parametro_anterior)
parametro_atual = [
'{0} : {1}'.format(key, evento['parametro_atual'][key])
for key in evento['parametro_atual']]
parametro_atual = u'\n'.join(parametro_atual)
try:
functionality = Functionality()
event_log = EventLog()
event_log.usuario = usuario
event_log.hora_evento = datetime.now()
event_log.acao = evento['acao']
event_log.funcionalidade = functionality.exist(
evento['funcionalidade'])
event_log.parametro_anterior = parametro_anterior
event_log.parametro_atual = parametro_atual
event_log.id_objeto = evento['id_objeto']
event_log.audit_request = evento['audit_request']
event_log.evento = ''
event_log.resultado = 0
event_log.save()
except Exception, e:
cls.logger.error(
u'Falha ao salvar o log: evento = %s, id do usuario = %s.' % (evento, usuario))
raise EventLogError(
e, u'Falha ao salvar o log: evento = %s, id do usuario = %s.' % (evento, usuario))
[docs]class EventLogQueue(object):
[docs] @classmethod
def log(cls, usuario, evento):
"""Send the eventlog to queues"""
usuario_id = 'NoUser'
if usuario:
usuario_id = usuario.id
# Send to Queue
queue_manager = QueueManager(
broker_vhost='tasks',
exchange_name='eventslog',
routing_key='eventslog'
)
queue_manager.append({
'action': evento['acao'],
'kind': evento['funcionalidade'],
'timestamp': int(time()),
'data': {
'id_object': evento['id_objeto'],
'user': usuario_id,
'old_value': evento['parametro_anterior'],
'new_value': evento['parametro_atual']
}
})
queue_manager.send()
[docs]class AuditRequest(models.Model):
"""
copied from https://github.com/leandrosouza/django-simple-audit
"""
THREAD_LOCAL = threading.local()
request_id = models.CharField(max_length=255)
request_context = models.CharField(max_length=255)
ip = models.IPAddressField()
path = models.CharField(max_length=1024)
date = models.DateTimeField(auto_now_add=True, verbose_name=_('Date'))
user = models.ForeignKey('usuario.Usuario')
class Meta:
db_table = u'audit_request'
[docs] @staticmethod
def new_request(path, user, ip, identity, context):
"""
Create a new request from a path, user and ip and put it on thread context.
The new request should not be saved until first use or calling method current_request(True)
"""
from networkapi.usuario.models import Usuario
if not isinstance(user, Usuario):
# try to find a Usuario with the same email
# Need to do this because we are using django 1.4 and we cannot
# change the user model
usuario, created = Usuario.objects.get_or_create(
user=user.username,
defaults={'ativo': user.is_active,
'nome': user.get_full_name(),
'email': user.email,
'user': user.username})
else:
usuario = user
audit_request = AuditRequest()
audit_request.ip = ip
audit_request.user = usuario
audit_request.path = path
audit_request.request_id = identity
audit_request.request_context = context
AuditRequest.THREAD_LOCAL.current = audit_request
return audit_request
[docs] @staticmethod
def set_request_from_id(request_id):
"""
Load an old request from database and put it again in thread context.
If request_id doesn'texist, thread context will be cleared
"""
audit_request = None
if request_id is not None:
try:
audit_request = AuditRequest.objects.get(request_id=request_id)
except AuditRequest.DoesNotExist:
pass
AuditRequest.THREAD_LOCAL.current = audit_request
[docs] @staticmethod
def current_request(force_save=False):
"""
Get current request from thread context (or None doesn't exist).
If you specify force_save,current request will be saved on database first.
"""
audit_request = getattr(AuditRequest.THREAD_LOCAL, 'current', None)
if force_save and audit_request is not None and audit_request.pk is None:
audit_request.save()
return audit_request
[docs] @staticmethod
def cleanup_request():
"""
Remove audit request from thread context
"""
AuditRequest.THREAD_LOCAL.current = None
[docs]class Functionality(models.Model):
nome = models.CharField(
max_length=50, primary_key=True, db_column='functionality')
logger = logging.getLogger('Funcionality')
class Meta:
db_table = u'functionality'
[docs] @classmethod
def exist(cls, event_functionality):
func = Functionality.objects.filter(nome=event_functionality)
if func.exists():
return event_functionality
else:
functionality = Functionality()
functionality.nome = event_functionality
functionality.save()
return event_functionality