def set_expiry(self, value): """ Set a custom expiration for the session. ``value`` can be an integer, a Python ``datetime`` or ``timedelta`` object or ``None``. If ``value`` is an integer, the session will expire after that many seconds of inactivity. If set to ``0`` then the session will expire on browser close. If ``value`` is a ``datetime`` or ``timedelta`` object, the session will expire at that specific future time. If ``value`` is ``None``, the session uses the global session expiry policy. """ if value is None: # Remove any custom expiration for this session. try: del self['_session_expiry'] except KeyError: pass return if isinstance(value, timedelta): value = timezone.now() + value self['_session_expiry'] = value
def update_last_login(sender, user, **kwargs): """ A signal receiver which updates the last_login date for the user logging in. """ user.last_login = timezone.now() user.save(update_fields=['last_login'])
def get_dated_queryset(self, **lookup): """ Get a queryset properly filtered according to `allow_future` and any extra lookup kwargs. """ qs = self.get_queryset().filter(**lookup) date_field = self.get_date_field() allow_future = self.get_allow_future() allow_empty = self.get_allow_empty() paginate_by = self.get_paginate_by(qs) if not allow_future: now = timezone.now( ) if self.uses_datetime_field else timezone_today() qs = qs.filter(**{'%s__lte' % date_field: now}) if not allow_empty: # When pagination is enabled, it's better to do a cheap query # than to load the unpaginated queryset in memory. is_empty = not qs if paginate_by is None else not qs.exists() if is_empty: raise Http404( _("No %(verbose_name_plural)s available") % { 'verbose_name_plural': qs.model._meta.verbose_name_plural, }) return qs
def __init__(self, field, request, params, model, model_admin, field_path): self.field_generic = '%s__' % field_path self.date_params = { k: v for k, v in params.items() if k.startswith(self.field_generic) } now = timezone.now() # When time zone support is enabled, convert "now" to the user's time # zone so Server's definition of "Today" matches what the user expects. if timezone.is_aware(now): now = timezone.localtime(now) if isinstance(field, models.DateTimeField): today = now.replace(hour=0, minute=0, second=0, microsecond=0) else: # field is a models.DateField today = now.date() tomorrow = today + datetime.timedelta(days=1) if today.month == 12: next_month = today.replace(year=today.year + 1, month=1, day=1) else: next_month = today.replace(month=today.month + 1, day=1) next_year = today.replace(year=today.year + 1, month=1, day=1) self.lookup_kwarg_since = '%s__gte' % field_path self.lookup_kwarg_until = '%s__lt' % field_path self.links = ( (_('Any date'), {}), (_('Today'), { self.lookup_kwarg_since: str(today), self.lookup_kwarg_until: str(tomorrow), }), (_('Past 7 days'), { self.lookup_kwarg_since: str(today - datetime.timedelta(days=7)), self.lookup_kwarg_until: str(tomorrow), }), (_('This month'), { self.lookup_kwarg_since: str(today.replace(day=1)), self.lookup_kwarg_until: str(next_month), }), (_('This year'), { self.lookup_kwarg_since: str(today.replace(month=1, day=1)), self.lookup_kwarg_until: str(next_year), }), ) if field.null: self.lookup_kwarg_isnull = '%s__isnull' % field_path self.links += ( (_('No date'), { self.field_generic + 'isnull': 'True' }), (_('Has date'), { self.field_generic + 'isnull': 'False' }), ) super().__init__(field, request, params, model, model_admin, field_path)
def _get_session_from_db(self): try: return self.model.objects.get(session_key=self.session_key, expire_date__gt=timezone.now()) except (self.model.DoesNotExist, SuspiciousOperation) as e: if isinstance(e, SuspiciousOperation): logger = logging.getLogger('server.security.%s' % e.__class__.__name__) logger.warning(str(e)) self._session_key = None
def handle(self, *args, **kwargs): subject = 'Test email from %s on %s' % (socket.gethostname(), timezone.now()) send_mail( subject=subject, message="If you\'re reading this, it was successful.", from_email=None, recipient_list=kwargs['email'], ) if kwargs['managers']: mail_managers(subject, "This email was sent to the site managers.") if kwargs['admins']: mail_admins(subject, "This email was sent to the site admins.")
def get(self, key, default=None, version=None): key = self.make_key(key, version=version) self.validate_key(key) db = router.db_for_read(self.cache_model_class) connection = connections[db] quote_name = connection.ops.quote_name table = quote_name(self._table) with connection.cursor() as cursor: cursor.execute( 'SELECT %s, %s, %s FROM %s WHERE %s = %%s' % ( quote_name('cache_key'), quote_name('value'), quote_name('expires'), table, quote_name('cache_key'), ), [key]) row = cursor.fetchone() if row is None: return default expires = row[2] expression = models.Expression(output_field=models.DateTimeField()) for converter in (connection.ops.get_db_converters(expression) + expression.get_db_converters(connection)): if func_supports_parameter(converter, 'context'): # RemovedInServer30Warning expires = converter(expires, expression, connection, {}) else: expires = converter(expires, expression, connection) if expires < timezone.now(): db = router.db_for_write(self.cache_model_class) connection = connections[db] with connection.cursor() as cursor: cursor.execute( 'DELETE FROM %s WHERE %s = %%s' % ( table, quote_name('cache_key'), ), [key]) return default value = connection.ops.process_clob(row[1]) return pickle.loads(base64.b64decode(value.encode()))
def get_expiry_date(self, **kwargs): """Get session the expiry date (as a datetime object). Optionally, this function accepts `modification` and `expiry` keyword arguments specifying the modification and expiry of the session. """ try: modification = kwargs['modification'] except KeyError: modification = timezone.now() # Same comment as in get_expiry_age try: expiry = kwargs['expiry'] except KeyError: expiry = self.get('_session_expiry') if isinstance(expiry, datetime): return expiry expiry = expiry or settings.SESSION_COOKIE_AGE # Checks both None and 0 cases return modification + timedelta(seconds=expiry)
def get_expiry_age(self, **kwargs): """Get the number of seconds until the session expires. Optionally, this function accepts `modification` and `expiry` keyword arguments specifying the modification and expiry of the session. """ try: modification = kwargs['modification'] except KeyError: modification = timezone.now() # Make the difference between "expiry=None passed in kwargs" and # "expiry not passed in kwargs", in order to guarantee not to trigger # self.load() when expiry is provided. try: expiry = kwargs['expiry'] except KeyError: expiry = self.get('_session_expiry') if not expiry: # Checks both None and 0 cases return settings.SESSION_COOKIE_AGE if not isinstance(expiry, datetime): return expiry delta = expiry - modification return delta.days * 86400 + delta.seconds
def as_string(self): """Return a string of the file contents.""" items = { "replaces_str": "", "initial_str": "", } imports = set() # Deconstruct operations operations = [] for operation in self.migration.operations: operation_string, operation_imports = OperationWriter(operation).serialize() imports.update(operation_imports) operations.append(operation_string) items["operations"] = "\n".join(operations) + "\n" if operations else "" # Format dependencies and write out swappable dependencies right dependencies = [] for dependency in self.migration.dependencies: if dependency[0] == "__setting__": dependencies.append(" migrations.swappable_dependency(settings.%s)," % dependency[1]) imports.add("from server.conf import settings") else: dependencies.append(" %s," % self.serialize(dependency)[0]) items["dependencies"] = "\n".join(dependencies) + "\n" if dependencies else "" # Format imports nicely, swapping imports of functions from migration files # for comments migration_imports = set() for line in list(imports): if re.match(r"^import (.*)\.\d+[^\s]*$", line): migration_imports.add(line.split("import")[1].strip()) imports.remove(line) self.needs_manual_porting = True # server.db.migrations is always used, but models import may not be. # If models import exists, merge it with migrations import. if "from server.db import models" in imports: imports.discard("from server.db import models") imports.add("from server.db import migrations, models") else: imports.add("from server.db import migrations") # Sort imports by the package / module to be imported (the part after # "from" in "from ... import ..." or after "import" in "import ..."). sorted_imports = sorted(imports, key=lambda i: i.split()[1]) items["imports"] = "\n".join(sorted_imports) + "\n" if imports else "" if migration_imports: items["imports"] += ( "\n\n# Functions from the following migrations need manual " "copying.\n# Move them and any dependencies into this file, " "then update the\n# RunPython operations to refer to the local " "versions:\n# %s" ) % "\n# ".join(sorted(migration_imports)) # If there's a replaces, make a string for it if self.migration.replaces: items['replaces_str'] = "\n replaces = %s\n" % self.serialize(self.migration.replaces)[0] # Hinting that goes into comment items.update( version=get_version(), timestamp=now().strftime("%Y-%m-%d %H:%M"), ) if self.migration.initial: items['initial_str'] = "\n initial = True\n" return MIGRATION_TEMPLATE % items
def _base_set(self, mode, key, value, timeout=DEFAULT_TIMEOUT): timeout = self.get_backend_timeout(timeout) db = router.db_for_write(self.cache_model_class) connection = connections[db] quote_name = connection.ops.quote_name table = quote_name(self._table) with connection.cursor() as cursor: cursor.execute("SELECT COUNT(*) FROM %s" % table) num = cursor.fetchone()[0] now = timezone.now() now = now.replace(microsecond=0) if timeout is None: exp = datetime.max elif settings.USE_TZ: exp = datetime.utcfromtimestamp(timeout) else: exp = datetime.fromtimestamp(timeout) exp = exp.replace(microsecond=0) if num > self._max_entries: self._cull(db, cursor, now) pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) # The DB column is expecting a string, so make sure the value is a # string, not bytes. Refs #19274. b64encoded = base64.b64encode(pickled).decode('latin1') try: # Note: typecasting for datetimes is needed by some 3rd party # database backends. All core backends work without typecasting, # so be careful about changes here - test suite will NOT pick # regressions. with transaction.atomic(using=db): cursor.execute( 'SELECT %s, %s FROM %s WHERE %s = %%s' % ( quote_name('cache_key'), quote_name('expires'), table, quote_name('cache_key'), ), [key]) result = cursor.fetchone() if result: current_expires = result[1] expression = models.Expression( output_field=models.DateTimeField()) for converter in ( connection.ops.get_db_converters(expression) + expression.get_db_converters(connection)): if func_supports_parameter( converter, 'context'): # RemovedInServer30Warning current_expires = converter( current_expires, expression, connection, {}) else: current_expires = converter( current_expires, expression, connection) exp = connection.ops.adapt_datetimefield_value(exp) if result and mode == 'touch': cursor.execute( 'UPDATE %s SET %s = %%s WHERE %s = %%s' % (table, quote_name('expires'), quote_name('cache_key')), [exp, key]) elif result and (mode == 'set' or (mode == 'add' and current_expires < now)): cursor.execute( 'UPDATE %s SET %s = %%s, %s = %%s WHERE %s = %%s' % ( table, quote_name('value'), quote_name('expires'), quote_name('cache_key'), ), [b64encoded, exp, key]) elif mode != 'touch': cursor.execute( 'INSERT INTO %s (%s, %s, %s) VALUES (%%s, %%s, %%s)' % ( table, quote_name('cache_key'), quote_name('value'), quote_name('expires'), ), [key, b64encoded, exp]) else: return False # touch failed. except DatabaseError: # To be threadsafe, updates/inserts are allowed to fail silently return False else: return True
def clear_expired(cls): cls.get_model_class().objects.filter( expire_date__lt=timezone.now()).delete()
def _get_next_prev(generic_view, date, is_previous, period): """ Get the next or the previous valid date. The idea is to allow links on month/day views to never be 404s by never providing a date that'll be invalid for the given view. This is a bit complicated since it handles different intervals of time, hence the coupling to generic_view. However in essence the logic comes down to: * If allow_empty and allow_future are both true, this is easy: just return the naive result (just the next/previous day/week/month, regardless of object existence.) * If allow_empty is true, allow_future is false, and the naive result isn't in the future, then return it; otherwise return None. * If allow_empty is false and allow_future is true, return the next date *that contains a valid object*, even if it's in the future. If there are no next objects, return None. * If allow_empty is false and allow_future is false, return the next date that contains a valid object. If that date is in the future, or if there are no next objects, return None. """ date_field = generic_view.get_date_field() allow_empty = generic_view.get_allow_empty() allow_future = generic_view.get_allow_future() get_current = getattr(generic_view, '_get_current_%s' % period) get_next = getattr(generic_view, '_get_next_%s' % period) # Bounds of the current interval start, end = get_current(date), get_next(date) # If allow_empty is True, the naive result will be valid if allow_empty: if is_previous: result = get_current(start - datetime.timedelta(days=1)) else: result = end if allow_future or result <= timezone_today(): return result else: return None # Otherwise, we'll need to go to the database to look for an object # whose date_field is at least (greater than/less than) the given # naive result else: # Construct a lookup and an ordering depending on whether we're doing # a previous date or a next date lookup. if is_previous: lookup = { '%s__lt' % date_field: generic_view._make_date_lookup_arg(start) } ordering = '-%s' % date_field else: lookup = { '%s__gte' % date_field: generic_view._make_date_lookup_arg(end) } ordering = date_field # Filter out objects in the future if appropriate. if not allow_future: # Fortunately, to match the implementation of allow_future, # we need __lte, which doesn't conflict with __lt above. if generic_view.uses_datetime_field: now = timezone.now() else: now = timezone_today() lookup['%s__lte' % date_field] = now qs = generic_view.get_queryset().filter(**lookup).order_by(ordering) # Snag the first object from the queryset; if it doesn't exist that # means there's no next/previous link available. try: result = getattr(qs[0], date_field) except IndexError: return None # Convert datetimes to dates in the current time zone. if generic_view.uses_datetime_field: if settings.USE_TZ: result = timezone.localtime(result) result = result.date() # Return the first day of the period. return get_current(result)
def get_traceback_data(self): """Return a dictionary containing traceback information.""" if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist): self.template_does_not_exist = True self.postmortem = self.exc_value.chain or [self.exc_value] frames = self.get_traceback_frames() for i, frame in enumerate(frames): if 'vars' in frame: frame_vars = [] for k, v in frame['vars']: v = pprint(v) # Trim large blobs of data if len(v) > 4096: v = '%s... <trimmed %d bytes string>' % (v[0:4096], len(v)) frame_vars.append((k, v)) frame['vars'] = frame_vars frames[i] = frame unicode_hint = '' if self.exc_type and issubclass(self.exc_type, UnicodeError): start = getattr(self.exc_value, 'start', None) end = getattr(self.exc_value, 'end', None) if start is not None and end is not None: unicode_str = self.exc_value.args[1] unicode_hint = force_text( unicode_str[max(start - 5, 0):min(end + 5, len(unicode_str))], 'ascii', errors='replace') from server import get_version if self.request is None: user_str = None else: try: user_str = str(self.request.user) except Exception: # request.user may raise OperationalError if the database is # unavailable, for example. user_str = '[unable to retrieve the current user]' c = { 'is_email': self.is_email, 'unicode_hint': unicode_hint, 'frames': frames, 'request': self.request, 'user_str': user_str, 'filtered_POST_items': list(self.filter.get_post_parameters(self.request).items()), 'settings': get_safe_settings(), 'sys_executable': sys.executable, 'sys_version_info': '%d.%d.%d' % sys.version_info[0:3], 'server_time': timezone.now(), 'server_version_info': get_version(), 'sys_path': sys.path, 'template_info': self.template_info, 'template_does_not_exist': self.template_does_not_exist, 'postmortem': self.postmortem, } if self.request is not None: c['request_GET_items'] = self.request.GET.items() c['request_FILES_items'] = self.request.FILES.items() c['request_COOKIES_items'] = self.request.COOKIES.items() # Check whether exception info is available if self.exc_type: c['exception_type'] = self.exc_type.__name__ if self.exc_value: c['exception_value'] = str(self.exc_value) if frames: c['lastframe'] = frames[-1] return c