Coder Social home page Coder Social logo

django-termsandconditions's People

Contributors

adrianocorrea avatar amarsahinovic avatar bcail avatar ciarancourtney avatar cyface avatar dependabot-preview[bot] avatar dependabot[bot] avatar grzegorzbialy avatar helgihg avatar kutenai avatar littlelamplight avatar mbatle avatar pyup-bot avatar raratiru avatar santtu avatar swainn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

django-termsandconditions's Issues

Avoid using inline javascript/css for content security policy

Some templates have inline javascript which is bad for content security policy.

https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions/templates/termsandconditions/snippets/termsandconditions.html

https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions_demo/templates/404.html

https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions_demo/templates/500.html

https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions_demo/templates/error.html

I cannot find any other ones. Also check if there is inline css anywhere. There should not be any inline css/javascript code.

You can use django-csp to test.

On a side note, I also see some jquery links in the demo templates. Why not use vanilla javascript instead of jquery? Bootstrap v5 is moving away from jquery for speed and other reasons like not relying on another library.

https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions_demo/templates/base.html

NoneType is not iterable

Hi,

While upgrading to the newer termsandconditions with an app I'm using (seahub), I encountered a failure. The following patches fixes things for me.

--- django-termsandconditions.orig/termsandconditions/models.py
+++ django-termsandconditions/termsandconditions/models.py
@@ -124,7 +124,7 @@ class TermsAndConditions(models.Model):

                 cache.set('tandc.not_agreed_terms_' + user.get_username(), not_agreed_terms, TERMS_CACHE_SECONDS)
             except (TypeError, UserTermsAndConditions.DoesNotExist):
-                return None
+                return []

         return not_agreed_terms

Changes proposal

Hi there!

I found your module quite interesting and relevant for our needs. However, for our use case, I would propose a couple of updates/changes:

  1. extending the model to include also additional info field, which would contain the message about the change (e.g. could be used as a summary of what is being changed and why). The point here to help users to digest the new terms.
  2. adding a template tag which would allow to display a modal with new terms, if such exists. This can be yet another means to communicate the new terms for users (e.g. by including the tag in the base template), an alternative to redirecting
  3. as and extra-add on, to allow for multi-language support (at least for the info) field

If you accept the proposal, I could work towards a respective pull request. Alternatively, if you don't approve, I'm okey with introducing these changes in a separate repo. Let me know.
In any case, thanks a lot for your work and efforts! ;)

Regards,
Adrian

Template tags to determine if user accepted terms or not

@cyface

Is there a template tag to determine if the user accepted or declined the terms and conditions? I want to do something like:

If user accepts:
<a href="/terms/active/">
​
Else:
<a href="/terms/">
​
Print Link With Template Tags:
<a href="/terms/print/{{slug}}/{{version}}/">

I am not sure what the condition of the if statement template tag would be to determine if the user accepted/declined the terms or not. Or if there is a template tag to determine active or not?

Also, what order / hierarchy would you recommend for an if statement like this?

Feel free to close this issue and reply with a comment I will search for it later on.

Feature request - Terms Checkbox On Signup Page For Consent & Middleware Setting

@cyface

This is a feature request. Be able to ask the user for their terms and conditions consent on the signup page via a checkbox that should submit to the terms and conditions database logs but then do not run the middleware after a successful signup for the first time. Then for new updates to the terms, the middleware could run normally.

Maybe have a setting like TERMS_MIDDLEWARE_ACTIVE_ON_SIGNUP = True|False would do the trick.

It occurred to me that doing something like asking for the user's PII like their email address on the signup page might be a violation of laws without their consent directly on that signup page. Since the current behavior with the middleware only allows a user to consent to the terms right after signing up and not during the signup page itself when it is already to late to consent about their PII being collected.

Here is my code below. Wondering how to get the checkbox to be able to log to the terms and conditions models instead of my own model especially without the user being created yet. I am using django-allauth's signup form. Or maybe I should just keep their response to the terms checkbox in my own model and not in the terms and conditions model?

Forms.py:

class CustomCheckbox(Field):
    template = 'custom_checkbox.html'

class SignupForm(SignupForm):
	terms_consent = forms.BooleanField(required=True,initial=False,label='I consent to the terms and conditions?')
	field_order = ['username', 'email', 'password1', 'password2', 'terms_consent',]
	def __init__(self, *args, **kwargs):
    	super(SignupForm, self).__init__(*args, **kwargs)
    	self.fields['terms_consent'].widget.attrs['class'] = ''
    	self.fields['terms_consent'].widget.attrs['type'] = 'checkbox'
    	self.helper = FormHelper()
    	self.helper.layout = Layout(
        	CustomCheckbox('is_age_compliant'),
    	)
	pass

	def save(self, request):
    	user = super().save(request)
    	profile = Profile(user=user,terms_consent=True)
    	user.save()
    	profile.save()
    	return user

	class Meta:
    	model = Profile
    	fields = ('terms_consent')

Signup.html:

<form class="signup" id="signup_form" autocomplete="off" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}
  {{ form.username|as_crispy_field }}
  {{ form.email|as_crispy_field }}
  {{ form.password1|as_crispy_field }}
  {{ form.password2|as_crispy_field }}
  {{ form.terms_consent|as_crispy_field }}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <button type="submit" class="btn btn-primary form-control">{% trans "Sign Up" %} &raquo;</button>
</form>

Custom Checkbox.html:

{% load crispy_forms_field %}

<div class="form-group">
  <div class="custom-control custom-checkbox">
    {% crispy_field field 'class' 'custom-control-input' %}
    <label class="custom-control-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
  </div>
</div>

Settings.py:

ACCOUNT_FORMS = {
    'signup': 'app.forms.SignupForm',
}

Models.py:

class Profile(models.Model):
	user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)
	terms_consent = models.BooleanField(default=False, blank=True, null=True,)

	def __str__(self):
    	return self.user.username

Version 2.0.3 Unable To View Content At /terms/ After Accepting

In 2.0.3 when I login and then accept the terms, I am unable to view any HTML content for the terms that this github project normally produces from the database entries. It just shows a blank page at /terms/ after accepting. When rolling back to 2.0.2, it works again and I am able to view the HTML content at /terms/ again after accepting.

If needed, perhaps rolling back this project back to 2.0.2 would be best. Regarding my previous issue, now I know that it is necessary to not re-name the slug to anything else other than site-terms so I do not mind reverting back to 2.0.2. The maintainer team of this project needs to decide moving forward whether they want to prevent accidental / custom changes to the slug in admin or in settings. Maybe make it a disabled field in admin. It would have been nice though to make your own custom slug but if not, so be it. If reverting back to 2.0.2, I highly recommend updating the documentation with a warning saying "Do not change the slug to anything other than site-terms".

AttributeError: module 'django.db.models' has no attribute 'permalink'

from future import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from six import python_2_unicode_compatible

@python_2_unicode_compatible
class Product(models.Model):
"""A generic Product"""
name = models.CharField(blank=True, max_length=100)
sites = models.ManyToManyField(Site)

def __str__(self):
    return self.name

@models.permalink
def get_absolute_url(self):
    return ('product_detail', [self.id])

def sites_str(self):
    return ', '.join([s.name for s in self.sites.all()])
sites_str.short_description = 'sites'

@python_2_unicode_compatible
class Vote(models.Model):
"""A Vote on a Product"""
user = models.ForeignKey(User, related_name='votes')
product = models.ForeignKey(Product)
site = models.ForeignKey(Site)
score = models.FloatField()

def __str__(self):
    return "Vote"   

Invalid input syntax for type inet: "85.136.1.206, 125.228.71.64"

(IPs have been modified)

For an unknown reason, there are sometimes 2 IP addresses and the insert in database crashes because of that.
I'm using TERMS_IP_HEADER_NAME = "HTTP_X_FORWARDED_FOR"

Maybe we can just split on ", " and only save the first IP address.

Complete stack trace:

ERROR:django.request:Internal Server Error: /terms/accept/
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type inet: "88.126.6.206, 165.225.76.60"
LINE 1: ..., "ip_address", "date_accepted") VALUES (2066, 2, '85.136.1....
                                                             ^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/termsandconditions/views.py", line 134, in post
    new_user_terms.save()
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 741, in save
    force_update=force_update, update_fields=update_fields)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 779, in save_base
    force_update, using, update_fields,
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 870, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 908, in _do_insert
    using=using, raw=raw)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/query.py", line 1186, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1375, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.DataError: invalid input syntax for type inet: "85.136.1.206, 125.228.71.64"
LINE 1: ..., "ip_address", "date_accepted") VALUES (2066, 2, '85.136.1....

OperationalError when trying to see the users that accepted the terms in admin

Hitting the change link in the User Terms and Conditions of Django admin, I receive the following error:

I have a custom user model where users authenticate using their email instead of a username along the lines of django docs, if I remember well.

I can post the whole structure if needed.

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/<my-custom-url>/admin/termsandconditions/usertermsandconditions/

Django Version: 1.11.4
Python Version: 3.4.2

Traceback:

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)

The above exception (target lists can have at most 1664 entries
) was the direct cause of the following exception:

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/contrib/admin/options.py" in wrapper
  551.                 return self.admin_site.admin_view(view)(*args, **kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/contrib/admin/sites.py" in inner
  224.             return view(request, *args, **kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapper
  67.             return bound_func(*args, **kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/utils/decorators.py" in bound_func
  63.                 return func.__get__(self, type(self))(*args2, **kwargs2)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/contrib/admin/options.py" in changelist_view
  1662.             selection_note=_('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/models/query.py" in __len__
  232.         self._fetch_all()

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/models/query.py" in _fetch_all
  1118.             self._result_cache = list(self._iterable_class(self))

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/models/query.py" in __iter__
  53.         results = compiler.execute_sql(chunked_fetch=self.chunked_fetch)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
  894.             raise original_exception

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
  884.             cursor.execute(sql, params)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  80.             return super(CursorDebugWrapper, self).execute(sql, params)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/utils.py" in __exit__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "/home/user/.virtualenvs/environment/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)

Exception Type: OperationalError at /<my-custom-url>/admin/termsandconditions/usertermsandconditions/
Exception Value: target lists can have at most 1664 entries

Problems following the guideline for translations

I've checked the guideline on this package to make the translations and I don't know if I'm doing something wrong or maybe the guidelines are outdated (because they are from 2015).

I could make the point 1 and point 2, but when trying to make the point 3. Add translation, when running the makemigrations command I get the following message:

No changes detected in app 'termsandconditions'

I attach my code blocks related to this implementation:

settings.py

LANGUAGES = (
    ('en', _('English')),
    ('es', _('Spanish')),
)

MIGRATION_MODULES = {
    # local path for migration for the termsandconditions
    'termsandconditions': 'ToS_translations.migrations.migrations_termsandconditions',
}

translation.py

from modeltranslation.translator import translator, TranslationOptions
from termsandconditions.models import TermsAndConditions


class TermsAndConditionsTranslationOptions(TranslationOptions):
    fields = ('name', 'text', 'info')


translator.register(TermsAndConditions, TermsAndConditionsTranslationOptions)

The structure of my project

-my_project
  - my_project
     - settings.py
     - ...
  - ToS_translations
     - migrations
         - migrations_termsandconditions
             - 001_initial.py
             - __init__.py
         - __init__.py
     - __init__.py
     - translation.py
  - other_apps

Thank you.

Problems when installing on a new venv

I'm trying to install the package to another computer which is using the same packages as the first one I got it installed and I'm having an error.

Information of the system:
Python 3.6
Django 2.2
PostgreSQL 12

The error:

Collecting django-termsandconditions==2.0.6
  Using cached django-termsandconditions-2.0.6.tar.gz (22 kB)
  Installing build dependencies: started
  Installing build dependencies: finished with status 'done'
  Getting requirements to build wheel: started
  Getting requirements to build wheel: finished with status 'error'

DEPRECATION: The -b/--build/--build-dir/--build-directory option is deprecated. pip 20.3 will remove support for this functionality. A possible replacement is use the TMPDIR/TEMP/TMP environment variable, possibly combined with --no-clean. You can find discussion regarding this at https://github.com/pypa/pip/issues/8333.
  ERROR: Command errored out with exit status 1:
   command: /Users/juanjo/PycharmProjects/ekiterplatform/venv/bin/python /Users/juanjo/PycharmProjects/ekiterplatform/venv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /var/folders/lh/5bwwxr2911z513712wt71l_80000gn/T/tmpdy3s1mne
       cwd: /private/var/folders/lh/5bwwxr2911z513712wt71l_80000gn/T/pycharm-packaging/django-termsandconditions
  Complete output (10 lines):
  Traceback (most recent call last):
    File "/Users/juanjo/PycharmProjects/ekiterplatform/venv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 280, in <module>
      main()
    File "/Users/juanjo/PycharmProjects/ekiterplatform/venv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 263, in main
      json_out['return_val'] = hook(**hook_input['kwargs'])
    File "/Users/juanjo/PycharmProjects/ekiterplatform/venv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 108, in get_requires_for_build_wheel
      backend = _build_backend()
    File "/Users/juanjo/PycharmProjects/ekiterplatform/venv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py", line 99, in _build_backend
      obj = getattr(obj, path_part)
  AttributeError: module 'setuptools.build_meta' has no attribute '__legacy__'
  ----------------------------------------
ERROR: Command errored out with exit status 1: /Users/juanjo/PycharmProjects/ekiterplatform/venv/bin/python /Users/juanjo/PycharmProjects/ekiterplatform/venv/lib/python3.6/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /var/folders/lh/5bwwxr2911z513712wt71l_80000gn/T/tmpdy3s1mne Check the logs for full command output.

If I try to uninstall and reinstall the package on the other computer it works just fine.

If you need any extra information please ask for it. Thank you

Optional terms and conditions together with a mandatory one

We would like to have two kinds of permissions. The first should be mandatory for using the site.
I've seen that this should be easily done with this package by using a middleware.
We would like to have a second kind if terms of conditions, where we ask our user for their permission to use their measurement data for scientific analyses. Agreeing to this second T&C should be optional, so the users should be able to use the site also if they do not give us their permission.

Is this possible out of the box?

I've seen that when using the middleware, all "active" T&Cs must be confirmed for using the site.
If we created this second T&C as "not active", would it be possible to ask users on first login whether they agree to it or not?

TERMS_EXCLUDE_URL_LIST with i18n_patterns for url

Seems like applications is not working correct with language code in urls.

For example settings config to:

TERMS_EXCLUDE_URL_LIST = ('/', '/terms/required/', '/logout', '/securetoo/')

doesn't trigger for actual logout url - /{language_code}/logout/

NoReverseMatch at /terms/

NoReverseMatch at /terms/

Reverse for 'tc_print_page' with arguments '('', '')' not found. 1 pattern(s) tried: ['terms/print/(?P[a-zA-Z0-9_.-]+)/(?P[0-9.]+)/$']

"GET /terms/ HTTP/1.1" 500 178082

Requested Terms and Conditions that Have Not Been Created.
Internal Server Error: /terms/

After navigating to 127.0.0.1:8000/terms/ I received the error above.

All of these other URLs work however after adding data to the terms and conditions models inside 127.0.0.1:8000/admin/:
/terms/print/terms_slug/1.0/
/terms/view/terms_slug/1.0/
/terms/email/
/terms/accept/

I am using Django 3.0.3, Python 3.7.3, and the latest version of django-termsandconditions 2.0.2.

In version 2.0 of django-termsandconditions in combination with Django 2.2.9 and Sqlite (not sure exactly if the Django version / database is to blame or the newly added django-termsandconditions project update for the error above), I was able to navigate to /terms/ without a problem as well as the other URL endings above.

In addition to this error, I want to point out that the build for this project says build error and "some check were not successful" and pyup has 4 updates as well. Maybe this problem is related to this? Otherwise please fix these as well as it makes people hesitant to install this project since github is displaying this to users.

I would also like for this project to work on the latest Django 3 and Python 3 and be Postgres 12 compatible. This error might be showing up because of my recent move to Postgres 12 and upgrade to Django 3.0.3 or because the this project was updated a few days ago. Not sure.

Django (1.11 at least) creates migrations for termsandconditions

The main difference I can see is the stripping of the bytestrings?

# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-06-27 07:12
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('termsandconditions', '0002_termsandconditions_info'),
    ]

    operations = [
        migrations.AlterField(
            model_name='termsandconditions',
            name='date_active',
            field=models.DateTimeField(blank=True, help_text='Leave Null To Never Make Active', null=True),
        ),
        migrations.AlterField(
            model_name='termsandconditions',
            name='info',
            field=models.TextField(blank=True, help_text="Provide users with some info about what's changed and why", null=True),
        ),
        migrations.AlterField(
            model_name='termsandconditions',
            name='slug',
            field=models.SlugField(default='site-terms'),
        ),
        migrations.AlterField(
            model_name='usertermsandconditions',
            name='date_accepted',
            field=models.DateTimeField(auto_now_add=True, verbose_name='Date Accepted'),
        ),
        migrations.AlterField(
            model_name='usertermsandconditions',
            name='ip_address',
            field=models.GenericIPAddressField(blank=True, null=True, verbose_name='IP Address'),
        ),
    ]

On a separate note, would you be open to a PR which excludes Users from accepting terms if they have a certain permission?

Accessing database during module loading

There's a problematic statement at https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions/forms.py#L13:

    terms = forms.ModelMultipleChoiceField(
        TermsAndConditions.get_active_list(as_dict=False),
        widget=forms.MultipleHiddenInput,
    )

where the TermsAndConditions.get_active_list returns a list of current terms in the database. I've run into a problem where this fails during unit tests when there is no database available and not used at all (using py.test for a set of tests that do not use models at all). This is because the code above tries to access a non-existent database.

Looking here there are also some other problems, so:

  1. Accessing database during module loading (generally a no-no)
  2. If the module is part of a long-running process, TermsAndConditions list is loaded only once, and if thus the terms are changed this is not reflected in the terms field (which was loaded earlier)

I think the solution would be to move settings terms field within the class constructor instead (there's already such action in https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions/forms.py#L24 for handling a case with explicit list). Any thoughts on this?

Multi terms: TOS and Privacy policy

It is possible by slug, but decorator check only DEFAULT_TERMS_SLUG:

TermsAndConditions.agreed_to_latest(request.user)
def agreed_to_latest(user, slug=DEFAULT_TERMS_SLUG):

Disable IP address tracking?

We don't want to store our users' IP addresses... would you be open to adding a setting to disable that feature?

How to best optimize URLs for SEO?

I guess this is a general question but this package has a lot of links and some of them have duplicate content.

Which links should be included in sitemap.xml and disallowed in robots.txt?

Some of the URLs can be accessed when the user is logged out and logged in. For instance, /terms/accept/, /terms/accept/site-terms/, /terms/accept/site-terms/version_number/ can all be accessed when logged out which doesn't make sense logically but I guess it is fine and doesn't need a code change as long as pressing accept does not do anything when logged out and logged in (only after previously accepting another time).

Google bot will probably see these links so I guess this would be a good way to do it?

sitemap.xml:

<url>
<loc>http://example.com/terms/view/site-terms/</loc>
<changefreq>always</changefreq>
<priority>0.9</priority>
</url>

Robot.txt:

Disallow:
/terms/
/terms/active/
/terms/accept/
/terms/accept/site-terms/
/terms/accept/site-terms/version_number/
/terms/view/site-terms/version_number/
/terms/email/
/terms/email/site-terms/version_number/
/terms/print/site-terms/version_number/

Off topic rant: If you were to make some of those views @login_required, it may have a conflict with django-allauth and django-two-factor-auth I discovered in some of my other issue reports if those packages are used together where a logged out user could access django-two-factor-auth admin login page from a valid login only view URL. (so i don't mind if you don't change the code because of this)

Repeated T&C redirections and cut text

Hello,

We implemented django-termsandconditions in two projects and both have issues when users accept the T&C, sometimes happen:

  1. After acceptance, T&C page appears again. If user exits the website and enters again, all is fine.
  2. When the T&C appears again, sometimes only the first and a half line is displayed.
  3. If T&C are correctly accepted and the redirection succeeds, if user goes to another page, then, T&C appear again.

In all cases the registry of acceptance is correctly added in the DB.

settings.py:

# Terms and conditions setup
TERMS_BASE_TEMPLATE = 'web_manager/base.html'
TERMS_EXCLUDE_URL_CONTAINS_LIST = {'/terms/', '/i18n/setlang/', }
TERMS_CACHE_SECONDS = 30    # 10 in the other project

MIGRATION_MODULES = {
    # local path for migration for the termsandconditions
    'termsandconditions': 'company.migrations.migrations_termsandconditions',
}

If developers provide an email, we can share a private video with the issues.

Thanks.

Delete old user acceptances in the database when user accepts newer version

This is a feature request. To avoid filling up the database with additional user acceptances every time the terms get updated, why not delete the previous user acceptances and only keep the acceptances for that user regarding the latest version that they just accepted? Only delete the previous acceptances for that user if they accept the newest terms version. If they have not yet accepted the newest terms version, keep the old acceptance entry logged in the database still.

To satisfy all people who use django-termsandconditions, a setting like DELETE_OLD_ON_ACCEPT=True|False or whatever you want to call it would be needed for this to turn this on or off. Because maybe tracking all user acceptances in the database is needed no matter what the version of the terms is and maybe for legal purposes old acceptances would be needed to remain tracked in the database?

Example:
User accepts version 1
User version 1 acceptance logged in the database
Terms updates to version 2
Same user accepts version 2
Same user acceptance from version 1 in the database gets deleted
Version 2 acceptance gets logged in the database for that user

Multiple terms activated in different contexts

Hello! I have a use case for having multiple terms for a site, but active within different contexts, such as depending on a user's role. So, I would want one set of terms active for the site for all users, but if a user is requesting access to particular functionality or other roles on the site, they may have to accept additional terms and conditions.

I've dealt with this for now by creating a second terms document but not activating it (i.e., the active dates are Null). Then, I wrote a new decorator that allows me to specify a specific terms slug required for that view. This activates that single terms for acceptance. It would be nice if there were a cleaner way to have terms active, but not "default" terms for all users.

The decorator I'm using:

import urlparse
from functools import wraps
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, QueryDict
from django.utils.decorators import available_attrs
from termsandconditions.models import TermsAndConditions, UserTermsAndConditions

def terms_required(terms_slug):
    def decorator(view_func):
        """
        This decorator checks to see if the user is logged in, and if so, if they have accepted the site terms.
        """

        @wraps(view_func, assigned=available_attrs(view_func))
        def _wrapped_view(request, *args, **kwargs):
            """Method to wrap the view passed in"""

            terms = TermsAndConditions.objects.filter(slug=terms_slug)[0]
            if not request.user.is_authenticated() or _agreed_to_terms( request.user, terms ):
                return view_func(request, *args, **kwargs)

            currentPath = request.META['PATH_INFO']
            accept_path = reverse( 'tc_accept_specific_version_page', args=[ terms.slug, terms.version_number ] )
            login_url_parts = list(urlparse.urlparse(accept_path))
            querystring = QueryDict(login_url_parts[4], mutable=True)
            querystring['returnTo'] = currentPath
            login_url_parts[4] = querystring.urlencode(safe='/')
            return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))

        return _wrapped_view
    return decorator

def _agreed_to_terms( user, terms ):
    try:
        UserTermsAndConditions.objects.get(user=user, terms=terms)
        return True
    except UserTermsAndConditions.MultipleObjectsReturned:
        return True
    except UserTermsAndConditions.DoesNotExist:
        return False

Enable handling ToS text fields as template

Hi,
I came across a use case, where a ToS text has to include other variables and e.g. urls defined by {% url 'my-url-name' %}. In general, the ToS text (or other field) could contain template-like syntax.

This could be done by including a terms.text in a form of a Template object and using the include tag. Thus, one would need to customize the respective template file and use there {% include terms.text|as_template %} instead of {{ terms.text|safe }}.
I can do a PR with an additional template tag, and help info. Let me know if you think this makes sense.

Django 1.10+ support

Are there any plans to support Django 1.10 and up?

A quick test against 1.11 gave the following stacktrace:

  File "/opt/master/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 82, in load_middleware
    mw_instance = middleware(handler)
TypeError: object() takes no parameters

How can I protect terms from being publicly accessible?

If a not logged in user, accesses <site-url>/terms the terms will be shown.

Is it possible to allow the showing of the terms only to logged-in users?

Otherwise, is it possible to change the terms slug to something like <site-url>/blah/blah/terms?

Update to 2.2?

Are you planning to update to Django 2.2? Our development team really likes django-termsandconditions and want to be able to use it.

Basic Custom Template for Terms and Conditions

MIssing from the documentation is a minimum custom template which caters for the terms and coditions.

It can be activated in the settings.py:

TERMS_BASE_TEMPLATE = 'admin/terms.html'

admin/terms.html

<!DOCTYPE html>
<html>
  <head>
    <title>[My Title]</title>
    {% block styles %}{% endblock %}
    <link href='<path-to-my-css>' rel='stylesheet' type='text/css' />
  </head>
  <body>
    <main>
      <h2>{% block title %}{% endblock %}</h2>
      {% block content %}{% endblock %}
    </main>
  </body>
</html>

The only issue is that the block title is wrapped between h2 tags since the block content includes an h1 tag already.

Spam Protection Question

This is kind of a dumb question. But would like to hear your thoughts. Feel free to close this issue if the answer is no.

https://github.com/cyface/django-termsandconditions/blob/master/termsandconditions/templates/termsandconditions/tc_accept_terms.html

Does the form on this page need a captcha / honeypot field to stop spam? The only thing a user / bot could really do is click accept to the terms and conditions and they can't really do anything else. But since it is a form I am not sure.

MIddleware causes 7 extra queries

You can force protection of your whole site by using the T&C middleware. Once activated, any attempt to access an authenticated page will first check to see if the user has accepted the active T&Cs. This can be a performance impact, so you can also use the _TermsAndConditionsDecorator to protect specific views, or the pipeline setup to only check on account creation.

I read the warning. However, I use django-debug-toolbar and I see that middleware use causes 7 extra queries, while 5 of them are duplicated 5 times. Is this OK?

The same number of queries appears when I use {% show_terms_if_not_agreed %} in the base.html template.

Django 2.1: AttributeError: module 'django.db.models' has no attribute 'permalink'

  File ".../lib/python3.6/site-packages/termsandconditions/models.py", line 63, in TermsAndConditions
    @models.permalink
AttributeError: module 'django.db.models' has no attribute 'permalink'

Django 2.1 has removed the permalink() decorator.

I think a fix would be something like:

from django.urls import reverse

...

    def get_absolute_url(self):
        return reverse(
            'tc_view_specific_version_page', 
            args=[self.slug, self.version_number])  # pylint: disable=E1101

Thanks for this app!

License of this package

Thanks for this package! I'm interested in using it for a web application for scientists in a particular field and I'm wondering what kind of license you want to choose for your package. Is it already decided?

Template tag error thrown on missing 'not_agreed_terms'

I've been trying to get a clean lot output, but I see this in my debug logs

2019-08-11 13:19:47,896 django.channels.server DEBUG    Daphne running, listening on 127.0.0.1:8000
2019-08-11 13:30:05,301 django.template DEBUG    Exception while resolving variable 'not_agreed_terms' in template 'home/home_page.html'.
Traceback (most recent call last):
  File "/Volumes/sharpertool/proj/gardentronic/gardentronic/.venv3/lib/python3.7/site-packages/django/template/base.py", line 829, in _resolve_lookup
    current = current[bit]
  File "/Volumes/sharpertool/proj/gardentronic/gardentronic/.venv3/lib/python3.7/site-packages/django/template/context.py", line 83, in __getitem__
    raise KeyError(key)
KeyError: 'not_agreed_terms'

During handling of the above exception, another exception occurred:

* THIS GOES ON FOR A LONG TIME *

It drove me crazy for a while, but I finally tracked it down to this the inclusion tag "show_terms_if_not_agreed"

The tag has this logic

    if not_agreed_terms and is_path_protected(url.path):
        return {'not_agreed_terms': not_agreed_terms, 'returnTo': url.path}
    else:
        return {}

The problem is that it returns without the value set for 'not_agreed_terms', and so that means that the snippet, which includes this:

{% if not_agreed_terms %}
    {% render_bundle 'terms_modal' 'css' 'ASSETS' %}

Will raise a template Exception unless the user has NOT agreed to terms, basically, all of the time.

  • SUGGESTION *
    Return the value set to "False", -- it's inverted logic, but it works..
    if not_agreed_terms and is_path_protected(url.path):
        return {'not_agreed_terms': not_agreed_terms, 'returnTo': url.path}
    else:
        return {'not_agreed_terms': False}

This cleans up the error logs, and it's a cleaner solution anyway. Oh, and it likely improves performance since the Django stack does not need to unwind a bunch of stack frames.

/terms/email/ and /terms/email/site-terms/version_number/ not working

The email form in /terms/email/ and /terms/email/site-terms/version_number/ is not working.

I actually do not need this feature at all and maybe including a setting to disable these links / form is a good idea?

I suppose if they do not work that is fine as long as it cannot be compromised by a hacker / spam bots.

App Name

Thanks for the great package! I recently upgraded to Django 2.0.13. Would it be possible to add:

app_name = 'terms_and_conditions'

to line 13 of the urls.py file to enable namespaces for Django-termsandconditions?

Thanks!

Please tag your releases in github

pip has 1.1.14 which is not tagged in github. This makes it hard to follow what is part of the release. Or is development happenning elsewhere?

Thanks a lot.

Wysiwyg editor

Hi! Great module so far. But it seems like some prettiness is missing. Can you include wysiwyg editor for T&C? Or i can create pull request i guess

TERMS_EXCLUDE_URL_LIST Regular Expressions For Custom Slug Name

Now that the user could use any custom slug name, there needs to be a way to define that new custom slug name in settings so that every time a user changes the slug in admin, settings will be updated automatically.

For example, instead of:
TERMS_EXCLUDE_URL_LIST = {'/terms/accept/site-policy/'}

Do something like (using regular expressions):
TERMS_EXCLUDE_URL_LIST = {'/terms/accept/.*/'}

Not sure if this is currently possible using the current code or not. Please let me know.

The reason I want to do this is because I am running this project twice in my Django project. Once is for my site's terms and conditions and the other time is for my site's privacy policy. I would love if this project had an exact github package copy but for privacy policy. Where any code change in the terms and conditions github would need to be changed in the privacy policy github and vice versa. If not, no big deal I will just have to copy this terms and conditions project and change the variables to privacy policy ones myself and add to my django project as an app every time there is an update to the code.

Note for other users who want to run this project twice: in the TERMS_EXCLUDE_URL_LIST and POLICY_EXCLUDE_URL_LIST (this I made from changing the variables) there needs to be an exclusion of every policy URL in the TERMS_EXCLUDE_URL_LIST like this: TERMS_EXCLUDE_URL_LIST = {'/policyrequired/', '/policy/', '/policy/accept/', '/policy/accept/site-policy/'} in order to run both projects at the same time.

django 1.8 support?

Thanks for this package - we've been using a fork of it.

I just installed django-termsandconditions from PyPI, and it upgraded my django 1.8 to 1.9. Looks like that's required in setup.py. Is it intentional to not support 1.8 LTS?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.