{ "info": { "author": "Gilles Fabio", "author_email": "gilles.fabio@gmail.com", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "django-safety\n=============\n\n.. image:: https://secure.travis-ci.org/ulule/django-safety.png?branch=master\n :alt: Build Status\n :target: http://travis-ci.org/ulule/django-safety\n\n\n**Generic Django application for safer user accounts.**\n\nFeatures\n--------\n\nSessions\n~~~~~~~~\n\n* User can see all active sessions\n* User can disable a given active session\n* User can disable all active sessions\n\nForce password change\n~~~~~~~~~~~~~~~~~~~~~\n\n* Administrators can require a password change for any user\n\nWorkflows\n---------\n\nSessions\n~~~~~~~~\n\n1. User logs in\n2. We connect the logic to the ``user_logged_in`` signal\n3. We create a new ``safety.models.Session`` instance\n4. User can see the list of her sessions (with IP, last activity and device information)\n5. User can delete a given session in the list\n6. We delete both the related ``safety.models.Session`` instance and related session in store\n7. User can delete all active sessions excepted the current one\n8. We proceed the same way: deleting instances and related sessions from store\n9. User logs out\n10. We connect the logic to the ``user_logged_out`` signal\n11. We delete the related ``safety.models.Session`` instance\n\nForce password change\n~~~~~~~~~~~~~~~~~~~~~\n\n1. Administrator creates a ``PasswordChange`` instance and sets ``required`` to ``True``\n2. When user logs in, it will be redirected to password change form\n3. Until the user does not change its password, it is not authorized to go elsewhere\n4. User changes its password\n5. It is now authorized to go elsewhere\n\nInstallation\n------------\n\nInstalling prerequisites\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nGeoIP library must be installed on your server.\n\nOn OS X with Homebrew:\n\n.. code-block:: bash\n\n brew install geoip\n\nYou also need the GeoIP databases.\n\nFor Django >= 1.9, download City and Country databases as binary (not CSV):\n\nhttp://dev.maxmind.com/geoip/geoip2/geolite2/\n\nFor Django 1.8, download City and Country legacy databases as binary (not CSV):\n\nhttp://dev.maxmind.com/geoip/legacy/geolite/\n\nCreate a directory wherever you want and uncompress these archives this\ndirectory. Once done, set ``GEOIP_PATH`` setting pointing to this directory:\n\n.. code-block:: python\n\n GEOIP_PATH = '/absolute/path/to/maxmind/db/directory'\n\nInstalling django-safety\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nInstall\n\n.. code-block:: bash\n\n $ pip install django-safety\n\nIn your ``settings.py``, add ``safety`` to ``INSTALLED_APPS``:\n\n.. code-block:: python\n\n INSTALLED_APPS = (\n # Your other apps here.\n 'safety',\n )\n\nIn your ``urls.py``, include ``safety.urls`` under ``safety`` namespace.\n\n.. code-block:: python\n\n urlpatterns = [\n # Your other URLs here.\n url(r'^security/', include('safety.urls', namespace='safety')),\n ]\n\nSynchronize the database:\n\n.. code-block:: bash\n\n $ python manage.py migrate safety\n\nGreat. The session feature is ready.\n\nIf you want to enable the \"force password change\" feature, read the next.\n\nEnabling \"force password change\" feature\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo enable this feature, you have two choices:\n\n* You want to protect only specific views? Use ``password_change_required()`` decorator\n* You want to protect your whole application? Use ``PasswordChangeMiddleware`` middleware\n\nThe decorator works as any Django view decorator.\n\n.. code-block:: python\n\n #\n # In your urls.py\n #\n\n from safety.decorators import password_change_required\n from .views import protect_me\n\n urlpatterns = [\n # Other URLs here.\n url(r'^protect-me/$', password_change_required(protect_me)),\n ]\n\n #\n # Or in your views.py (it's up to you)\n #\n from django.shortcuts import render\n from safety.decorators import password_change_required\n\n @password_change_required\n def protect_me(request):\n return render(request, 'protect_me.html')\n\nThe middleware works as any Django middleware.\n\nAdd ``safety.middleware.PasswordChangeMiddleware`` middleware in your ``settings.py``:\n\n.. code-block:: python\n\n MIDDLEWARE_CLASSES = [\n 'django.middleware.security.SecurityMiddleware',\n 'django.contrib.sessions.middleware.SessionMiddleware',\n 'django.middleware.common.CommonMiddleware',\n 'django.middleware.csrf.CsrfViewMiddleware',\n 'django.contrib.auth.middleware.AuthenticationMiddleware',\n 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',\n 'django.contrib.messages.middleware.MessageMiddleware',\n 'django.middleware.clickjacking.XFrameOptionsMiddleware',\n 'safety.middleware.PasswordChangeMiddleware',\n ]\n\nDone.\n\nSettings\n--------\n\n+-------------------------------------------+---------------------------------------------------------------------+\n| Setting | Description |\n+===========================================+=====================================================================+\n| ``SAFETY_LOGIN_REQUIRED_MIXIN_CLASS`` | The Python path to your own \"login required\" mixin class. |\n| | Defaults to ``safety.mixins.LoginRequiredMixin``. |\n+-------------------------------------------+---------------------------------------------------------------------+\n| ``SAFETY_IP_RESOLVER`` | The Python path to your own IP resolver callable. |\n| | Defaults to ``safety.resolvers.remote_addr_ip``. |\n+-------------------------------------------+---------------------------------------------------------------------+\n| ``SAFETY_DEVICE_RESOLVER`` | The Python path to your own device resolver callable. |\n| | Defaults to ``safety.resolvers.device``. |\n+-------------------------------------------+---------------------------------------------------------------------+\n| ``SAFETY_LOCATION_RESOLVER`` | The Python path to your own location resolver callable. |\n|\u00a0 |\u00a0Defaults to ``safety.resolvers.location``. |\n+-------------------------------------------+---------------------------------------------------------------------+\n\nDevelopment\n-----------\n\n.. code-block:: bash\n\n # Install pip and virtualenv\n $ sudo easy_install pip\n $ sudo pip install virtualenv\n\n # Clone repository\n $ git clone https://github.com/ulule/django-safety.git\n\n # Setup your development environment\n $ cd django-safety\n $ make devenv\n $ source .venv/bin/activate\n\n # Download GeoIP databases\n $ make geoip\n\n # Launch test suite\n $ make test\n\n # Launch test suite with tox to check compatibility\n $ tox\n\n # Run the example project (default user username is \"johndoe\")\n $ make example-migrate\n $ make example-user\n $ make example-serve\n\nContribute\n----------\n\n1. Create an issue (**before** submitting pull requests)\n2. Submit your bug or feature request\n3. You want to fix or code it yourself? Great! Fork the project\n4. Create a branch, always add tests and make sure they all pass with ``tox``\n5. Submit a pull request\n\nCompatibility\n-------------\n\n- python 2.7: Django 1.8, 1.9\n- Python 3.4: Django 1.8, 1.9\n- Python 3.5: Django 1.8, 1.9", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/ulule/django-safety", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "django-safety", "package_url": "https://pypi.org/project/django-safety/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-safety/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/ulule/django-safety" }, "release_url": "https://pypi.org/project/django-safety/0.1.0/", "requires_dist": null, "requires_python": null, "summary": "Generic Django application for safer user accounts", "version": "0.1.0" }, "last_serial": 2007665, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "b699d628d91b4749140c18e945e6bc31", "sha256": "c00378bdf74988cb562206b3825bcfaba6addd3d9ebdff9f8edb9e2f27ac143b" }, "downloads": -1, "filename": "django-safety-0.1.0.tar.gz", "has_sig": true, "md5_digest": "b699d628d91b4749140c18e945e6bc31", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13216, "upload_time": "2016-03-15T11:46:17", "url": "https://files.pythonhosted.org/packages/49/f3/2e8e2f9fad5bd1abe4a3792fe7e12be28f32ae6c059291f75968b5251db1/django-safety-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b699d628d91b4749140c18e945e6bc31", "sha256": "c00378bdf74988cb562206b3825bcfaba6addd3d9ebdff9f8edb9e2f27ac143b" }, "downloads": -1, "filename": "django-safety-0.1.0.tar.gz", "has_sig": true, "md5_digest": "b699d628d91b4749140c18e945e6bc31", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13216, "upload_time": "2016-03-15T11:46:17", "url": "https://files.pythonhosted.org/packages/49/f3/2e8e2f9fad5bd1abe4a3792fe7e12be28f32ae6c059291f75968b5251db1/django-safety-0.1.0.tar.gz" } ] }