Getting user`s UUID from django server - python

I have a django server with an admin panel.
Different users make changes there and this is saved via auditlog in the database and displayed in the "history".
But there are situations when a user enters under the account of another user and makes changes on his behalf.
In order to identify from which device this or that change was made, it was a nice decision to also record data about the IP of the user from whom the change was made, and his unique device number.
By overloading several methods in the "AuditlogMiddleware" class, I got the desired result via "uuid.UUID(int=uuid.getnode())".
(Tested locally, because the prod server is heavily loaded and there is no way to do test committees)
from __future__ import unicode_literals
import threading
import time
from auditlog.middleware import AuditlogMiddleware
threadlocal = threading.local()
class ExtendedAuditlogMiddleware(AuditlogMiddleware):
def process_request(self, request):
threadlocal.auditlog = {
'signal_duid': (self.__class__, time.time()),
'remote_addr': request.META.get('REMOTE_ADDR'),
}
super(ExtendedAuditlogMiddleware, self).process_request(request)
**#changes here
import uuid
threadlocal.auditlog['additional_data'] = str(uuid.UUID(int=uuid.getnode()))+" | "+request.META["USERNAME"]**
# #staticmethod
def set_actor(self, user, sender, instance, signal_duid, **kwargs):
super(ExtendedAuditlogMiddleware, self).set_actor(user, sender, instance, signal_duid, **kwargs)
**#changes here
instance.additional_data = threadlocal.auditlog['additional_data']**
But the problem is that I think I get the UUID not of the user, but of the server, because there is no access to the user, i guess. I couldn't find the information, and I couldn't come up with my own solution either.
Question - is it even possible to get information from the server about django admin users' devices??
If not, what can i use instead of UUID to identify which device was used while making changes in django admin panel??
Thank you all in advance!

try to use javascript in side of your template to send this info thrugh

Related

notify user if similar model created _Django

I have a model.that I need to if any model with specific field created in database.send a Email to user for notify.I did some search too many apps are there for handling the notify. thats not my concern .I dont know how deploy this structure.any guide or example for this.for example :
if x = book.objects.create(title="book1") :
print("the book created")
if this action happend do something.
If you need to monitor object creation globally the best thing to use is signals
Like so:
from .models import Book
from django.db.models.signals import post_save
def book_created(sender, instance, created, **kwargs):
if created and instance.title == 'book1':
#logic here
post_save.connect(save_profile, sender=Book)
you need to stick that post_save.connect() function somewhere where it will be evaluated when the app is run, you can use app_dir/app.py for instance.

What is best practice to verify the user in google app engine (gae) for every request? Or how to avoid DB access?

I am working on a google app engine (gae) project in python which has the following structure:
class LoginHandler(webapp2.RequestHandler):
def get(self):
...#check User-> DB access
def post():
...#check User-> DB access
class SignupHandler(webapp2.RequestHandler):
def get(self):
...#check User-> DB access
def post():
...#check User-> DB access
class Site1Handler(webapp2.RequestHandler):
def get(self):
...#check User-> DB access
def post():
...#check User-> DB access
class Site2Handler(webapp2.RequestHandler):
def get(self):
...#check User-> DB access
def post():
...#check User-> DB access
class ...
application = webapp2.WSGIApplication([('/login', LoginHandler),
('/signup',SignupHandler),
('/site1', Site1Handler),
('/site2', Site2Handler),
...,
],
debug=True)
Every user who wants to use this application has to be logged in.
Therefore on the login-site and the signup-site a cookie value with an user_id is set.
So lets imagine this app has 100 URLs and the corresponding 100 Site...Handlers() implemented.
Than for every get()/post() call I first get the user_id from the cookie and check in the database if this user exists and if it is valid.
So if the user clicks on 20 sites the app accesses 20 times the db to validate the user.
I am sure there is a better way and I would be glad if someone could show me how to do this.
I have already seen someone inherited his own Handler from webapp2.RequestHandler
which would than look like:
class MyHandler(webapp2.RequestHandler):
def initialize(self, *a, **kw):
webapp2.RequestHandler.initialize(self, *a, **kw)
uid = self.request.cookies.get('user_id')
self.user = uid and User.all().filter('userid =', uid).get()
class LoginHandler(MyHandler):
def get(self):
...#if self.user is valid -> OK
def post():
...#if self.user is valid -> OK
...
And here it is getting confusing for me.
Consider two or more people accessing the application concurrently. Will then User1 see data of User2 because self.user is initialized with data from User2?
I also concidered using a global variable to save the current user. But here the same problem if two users access the app concurrent.
I also found the webapp2.registry functionality which seemed to me the same like a global dictionary. And here also the problem of two or more users accessing the app at the same time.
Could someone please show me how to do it right? I am very new to gae and very happy for every hint in the right direction.
(Maybe Memcached is the solution. But I am more interested in a review of this check if user is valid pattern. So what would be best practice to do this?)
Assuming that you are using NDB and validating your user by getting a User object via a key/id - it will be automatically cached in memcache as well as in current local instance's memory, so your route handlers won't be calling Datastore with every single request, this is all done automatically, no extra coding required. If for validation / getting the user object you are using a query - the result won't be automatically cached but you can always manually cache it and verify the user via cache first and if the cache doesn't exist only then query Datastore, caching the results for the next request.
See more here.
If you are using webapp2's Sessions with signed/secure cookies then the data in those cookies, including the fact that the user is validated (which you previously set when when validating the user the first time) can be trusted, as long as you use long and randomly generated secret_key, that is kept secret and thus, just like with cache, you first check whether the user is validated in the cookie and if not, you ask Datastore and save the result in the session cookie for the next request. See more here.
Either way, you don't have to repeat your validation code in every single handler like you are showing in your example. One way of fixing it would be using decorators which would make your validation reuse as simple as placing #login_required before your get method. See more info here and take a look at the webapp2_extras.appengine.users file to get an idea how to write your own, simmilar decorator.

Django functional LiveServerTestCase - After submitting form with selenium, objects save to non-test database

Absolutely losing my brain over this. I can't figure out why this is happening. Each time I run this test, the object gets saved to the normal, non-test database. However, both assertions at the end of the test fail anyway, saying they can't find ANY users in the database, even though each time the test runs I have to go into the admin to delete the objects it's created on localhost. I'm using SQLITE3 in my settings, and I understand that SQLITE tests are supposed to run in memory, rather than hitting the database. I've searched and searched and can't find any useful information on the web. Here's the test function:
import time
import datetime
from django.test import TestCase, LiveServerTestCase
from django.core.urlresolvers import resolve
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from django.contrib.auth.models import User
from apps.registration.forms import RegistrationForm
class NewVisitorTest(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(3)
def tearDown(self):
self.browser.quit()
def test_registration_process(self):
# Goes to registration page
self.browser.get('http://localhost:8000/register/')
# User can find sign up form
registration_form = self.browser.find_element_by_id('id_registration_form')
# User can fill out sign up form
first_name_input = self.browser.find_element_by_id('id_first_name')
first_name_input.send_keys('Jim')
last_name_input = self.browser.find_element_by_id('id_last_name')
last_name_input.send_keys('Barrow')
date = datetime.date.today()
date_input = self.browser.find_element_by_id('id_birthday')
date_input.send_keys(str(date))
username_input = self.browser.find_element_by_id('id_username')
username_input.send_keys('jim_barrow')
password_input = self.browser.find_element_by_id('id_password')
password_input.send_keys('kittensarecute')
password_1_input = self.browser.find_element_by_id('id_password1')
password_1_input.send_keys('kittensarecute')
email_input = self.browser.find_element_by_id('id_email')
email_input.send_keys('jim_barrow#gmail.com')
# User can submit sign up form
registration_form.submit()
# User is now registered as a user object
users = User.objects.all()
self.assertEqual(len(users), 1)
# User is now registered as a person object
persons = Person.objects.all()
self.assertEqual(len(persons), 1)
if __name__ == '__main__':
unittest.main()
If there's any other context I can provide, I'll happily show you. This is practically a blank project, so there aren't any strange or unusual settings in settings.py which might confuse things. Any help would be greatly appreciated.
According to the LiveServerTestCase docs, the live server is on port 8081 by default. However you are fetching the page from port 8000 instead.
I expect you are running the dev server on port 8000 and your tests are connecting to it, so your new objects appear in the non-test database. You need to change your code to fetch the page from port 8081 instead.
Quick Update:
As of Django 1.11, the server setup by LiveServerTestCase uses any free port assigned by the localhost, not simply 8081.
You can access the live server URL and port using self.live_server_url, as per docs

Unsure how/where to manipulate Django objects

Okay so I am very new to Django and relatively new to Python as well. In the website I am building, I am using some middleware that someone else made to keep track of "online" users using the cache to do so. Here is the middleware I'm referring to
import datetime
from django.core.cache import cache
from django.conf import settings
class ActiveUserMiddleware:
def process_request(self, request):
current_user = request.user
if request.user.is_authenticated():
now = datetime.datetime.now()
cache.set('seen_%s' % (current_user.username), now,
settings.USER_LASTSEEN_TIMEOUT)
I want to take all of the online users, then divide them based on whether they are in highschool or college (which is an attributed I gave users via foreign key to a profile), and then return a random user from the list of online users who meet those certain requirements. I am at a loss on how to do this because the django structure is still confusing me. Would I implement this in a view or in a model? After looking at the code for the active_users app I have figured out that I can import the active_users, but I'm not sure if that is a list, an array, or an object. Also how do I determing the number of online_users? Does something like online_users.length work? Here is the code I have come up with so far: (I have omitted some other imports and views for the sake of brevity). I'm sorry I haven't come up with a lot of code on my own, I am just very stuck/frustrated. Any help is greatly appreciated.
from online_status.status import CACHE_USERS
from online_status.utils import encode_json
from django.contrib.auth.models import User
from django.core.cache import cache
from django.template.context import RequestContext
def send_to(request):
sender = request.user
sender_level = sender.username
online_users = cache.get(CACHE_USERS)
match_users=[]
for User in online_users:
if User.username == sender_level:
match_users.append(user)
random_user = choice(match_users)
html = "<html> <body> <p> User: %s % random_user </p></body></html>" % random_user
return render_to_response(html)
With a cache based seen info you need to extract the user name from the db to be able to get online users.
So the only way would be to filter UserProfile.objects.all() based on the value of the cache.
Then you can do
from random import choice
random_user = choice(online_users)
But it would be more efficient for those kinds of requests to store the seen info in your model. This way you could directly do a request like :
online_users = UserProfile.objects.filter(seen__lte=now-timeout)
In a typical use you would have a lot of users but a few online users. So the first version would be really slower.

satchmo mail.py send html email instead of text email

For my current satchmo store, I would like to send html email instead of all the txt email. By the looks of the satchmo_store account registration code, all the emails are hardcoded and uses .txt format instead of html format.
e.g. mail.py
"""Sends mail related to accounts."""
from django.conf import settings
from django.utils.translation import ugettext
from satchmo_store.mail import send_store_mail
from satchmo_store.shop.models import Config
from satchmo_store.shop.signals import registration_sender
import logging
log = logging.getLogger('satchmo_store.accounts.mail')
# TODO add html email template
def send_welcome_email(email, first_name, last_name):
"""Send a store new account welcome mail to `email`."""
shop_config = Config.objects.get_current()
subject = ugettext("Welcome to %(shop_name)s")
c = {
'first_name': first_name,
'last_name': last_name,
'site_url': shop_config.site and shop_config.site.domain or 'localhost',
'login_url': settings.LOGIN_URL,
}
send_store_mail(subject, c, 'registration/welcome.txt', [email],
format_subject=True, sender=registration_sender)
I know you can change the last line to the following in order to make it work:
send_store_mail(
subject=subject,
context=c,
template='registration/welcome.txt',
recipients_list=[email],
format_subject=True,
sender=registration_sender,
template_html='registration/welcome.html')
However, it would be in my best interest not to touch the code in Satchmo app for the upgrade purpose in the near future.
Does anyone know what would be the ideal way to override this function or enable the html email for all the registration related functions without touching the satchmo app?
Thanks in advance.
I have done similar changes to Satchmo internals in the following way:
It should be possible to copy the relevant file from the Satchmo installation into your django application. If you set up your Satchmo shop according to this recommendation, that would likely mean copying satchmo/apps/satchmo_store/accounts/mail.py to /localsite/accounts/mail.py. The idea is to automatically load the local copy instead of the original.
In your local copy of mail.py you could then replace the send_store_email() function. Keep a note so that you will remember your changes when it comes to a Satchmo upgrade. Quite likely the original file will still be the same, and your override will work even with future versions.
In other cases when you have to change some class behaviour you can also subclass the original class with one changing only the relevant methods, while keeping the original name.

Categories

Resources