<commit_before>= Django (yet another) Model Publisher

Publisher workflow for django models and Django CMS pages.

This is a fork of [[https://github.com/andersinno/django-model-publisher-ai|andersinno/django-model-publisher-ai]] which is a fork of the origin [[https://github.com/jp74/django-model-publisher|jp74/django-model-publisher]].

| {{https://travis-ci.org/wearehoods/django-ya-model-publisher.svg|Build Status on travis-ci.org}} | [[https://travis-ci.org/wearehoods/django-ya-model-publisher/|travis-ci.org/wearehoods/django-ya-model-publisher]] |
| {{https://codecov.io/gh/wearehoods/django-ya-model-publisher/branch/develop/graph/badge.svg|Coverage Status on codecov.io}} | [[https://codecov.io/gh/wearehoods/django-ya-model-publisher|codecov.io/gh/wearehoods/django-ya-model-publisher]] |
| {{https://coveralls.io/repos/wearehoods/django-ya-model-publisher/badge.svg|Coverage Status on coveralls.io}} | [[https://coveralls.io/r/wearehoods/django-ya-model-publisher|coveralls.io/r/wearehoods/django-ya-model-publisher]] |

== Features

* Django CMS page support.
* Add request/reject buttons in Django CMS toolbar.
* Django CMS placeholders support.
* Hvad/Parler support.
* Restrict user access to publish functions with user permissions.


== base info

We have these three user types:

* A user with only a few rights (we call it **'reporter'**)
* A user with more rights (We call it **'editor'**)
* The superuser with all rights

The user case is following:

* **'reporter'**:
** can only change draft content
** can't change public content
** can't delete publisher model entries or CMS pages.
** can send a //(un-)publish request// to the 'editor' with a text node.

* **'editor'**:
** can response open publishing request from 'reporter'.
** can change drafts and public content, but only if there is no pending request.
** can delete publisher model entries or CMS pages.
** can't delete/manipulate publisher state model entries.


== permissions

Permissions for **'reporter'** who can only create //(un-)publish requests//:
{{{
...
[ ] cms.publish_page
...
[*] cms.add_page
[*] cms.change_page
[ ] cms.delete_page
...
[ ] publisher.add_publisherstatemodel
[*] publisher.change_publisherstatemodel
[ ] publisher.delete_publisherstatemodel
...
[ ] <app_name>.can_publish_<model_name>
...
[*] <app_name>.add_<model_name>
[*] <app_name>.change_<model_name>
[ ] <app_name>.delete_<model_name>
...
}}}


Permissions for **'editor'** who can //accept/reject (un-)publish requests//:
{{{
...
[*] cms.publish_page
...
[*] cms.add_page
[*] cms.change_page
[*] cms.delete_page
...
[ ] publisher.add_publisherstatemodel
[*] publisher.change_publisherstatemodel
[ ] publisher.delete_publisherstatemodel
...
[*] <app_name>.can_publish_<model_name>
...
[*] <app_name>.add_<model_name>
[*] <app_name>.change_<model_name>
[*] <app_name>.delete_<model_name>
...
}}}

**Important**: To prevent a privilege escalation, both users must **not** have access to these models:

* django.contrib.auth.models.Permission
* django.contrib.auth.models.Group
* cms.models.PagePermission

== Test users:

See user permission tests in:

* [[https://github.com/wearehoods/django-ya-model-publisher/blob/master/publisher_tests/test_basics.py|publisher_tests.test_basics.PermissionTestCase]]


== Django compatibility

|= django-ya-model-publisher |= django version      |= python            |
| >=v0.5.x                   | 1.8, 1.9, 1.10, 1.11 | 3.5, 3.6           |
| v0.4.x                     | 1.8, 1.9, 1.10, 1.11 | 2.7, 3.4, 3.5, 3.6 |

Note: See travis/tox config files for current test matrix


== run tests

run tests via //py.test// with current python/environment:
{{{
$ make test
or
$ ./setup.py test
or
$ python tests/manage.py test myapp
}}}

run test via //tox// e.g.:
{{{
$ make tox
or
$ ./setup.py tox
or
$ tox
}}}


=== run test project


You can run the test environment by:

{{{
$ ./run_test_project_dev_server.sh
}}}
or:
{{{
$ ./publisher_test_project/manage.py run_test_project_dev_server
}}}


The following steps will be executed:

* Create django users if not exists:
** A django **'superuser'**
** The user **editor**: He can accept/reject un-/publish requests
** The user **reporter**: He can create un-/publish requests
** note: Both users will used the same password as the 'superuser' !
* run migration
* insert test fixtures (Create Django CMS pages)
* collect static files
* run the django development server on localhost


You can pass arguments to the helper script, e.g.:
{{{
$ ./run_test_project_dev_server.sh --help
...
usage: manage.py run_test_project_dev_server [-h] [--version] [-v {0,1,2,3}]
                                             [--settings SETTINGS]
                                             [--pythonpath PYTHONPATH]
                                             [--traceback] [--no-color]
                                             [--ipv6] [--nothreading]
                                             [--noreload] [--nostatic]
                                             [--insecure]
                                             [addrport]
...
}}}


To 'reset' the test fixtures, run this:
{{{
$ ./publisher_test_project/manage.py create_test_data --fresh
}}}

For a complete fresh database, just remove the sqlite file, e.g.:
{{{
$ rm publisher_test_project/publisher_test_database.sqlite3
}}}


== Backwards-incompatible changes

=== v0.6.0

The permission names changed! Please update your django user permissions, too.

These permissions are removed:
* direct_publisher
* ask_publisher_request
* reply_publisher_request

Please read the information above.

== history

* v0.6.1 - 28.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.6.0...v0.6.1|compare v0.6.0...v0.6.1]]
** remove own "unique_together": Add {{{"publisher_is_draft"}}} to your own "unique_together" tuple
** remove out dated manage command "update_permissions" (can be found in [[https://github.com/jedie/django-tools|django-tools]])
* v0.6.0 - 27.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.5.1...v0.6.0|compare v0.5.1...v0.6.0]]
** refactor permissions and publisher workflow
** NEW: {{{publisher.views.PublisherCmsViewMixin}}}
** NEW: {{{publisher.admin.VisibilityMixin}}}
** bugfix django v1.11 compatibility
** Expand tests with {{{publisher_test_project.publisher_list_app}}}
* v0.5.1 - 20.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.5.0...v0.5.1|compare v0.5.0...v0.5.1]]
** fix python package (add missing parts)
** change travis/tox/pytest configuration
** minor code update
* v0.5.0 - 19.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.4.1...v0.5.0|compare v0.4.1...v0.5.0]]
** Skip official support for python v2.7 and v3.4 (remove from text matrix)
** Implement "request/reject/accept publishing" workflow with a shot messages and logging
** Add "request/reject/accept publishing" buttons to Django CMS toolbar for cms pages.
* v0.4.1 - 14.11.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.4.0.dev1...v0.4.1|compare v0.4.0.dev1...v0.4.1]]
** Refactor test run setup
** bugfix project name
* v0.4.0.dev1 - 14.11.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.3.1...v0.4.0.dev1|compare v0.3.1...v0.4.0.dev1]]
** Just create the fork and apply all pull requests from [[https://github.com/andersinno/django-model-publisher-ai/pull/14|andersinno/django-model-publisher-ai/pull/14]]

== links ==

| Homepage      | http://github.com/wearehoods/django-ya-model-publisher
| PyPi.org      | https://pypi.org/project/django-ya-model-publisher/
| PyPi (legacy) | http://pypi.python.org/pypi/django-ya-model-publisher/


== donation ==

* [[https://www.paypal.me/JensDiemer|paypal.me/JensDiemer]]
* [[https://flattr.com/submit/auto?uid=jedie&url=https%3A%2F%2Fgithub.com%2Fwearehoods%2Fdjango-ya-model-publisher%2F|Flattr This!]]
* Send [[http://www.bitcoin.org/|Bitcoins]] to [[https://blockexplorer.com/address/1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F|1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F]]
<commit_msg>+== Primary key type compatibility<commit_after>= Django (yet another) Model Publisher

Publisher workflow for django models and Django CMS pages.

This is a fork of [[https://github.com/andersinno/django-model-publisher-ai|andersinno/django-model-publisher-ai]] which is a fork of the origin [[https://github.com/jp74/django-model-publisher|jp74/django-model-publisher]].

| {{https://travis-ci.org/wearehoods/django-ya-model-publisher.svg|Build Status on travis-ci.org}} | [[https://travis-ci.org/wearehoods/django-ya-model-publisher/|travis-ci.org/wearehoods/django-ya-model-publisher]] |
| {{https://codecov.io/gh/wearehoods/django-ya-model-publisher/branch/develop/graph/badge.svg|Coverage Status on codecov.io}} | [[https://codecov.io/gh/wearehoods/django-ya-model-publisher|codecov.io/gh/wearehoods/django-ya-model-publisher]] |
| {{https://coveralls.io/repos/wearehoods/django-ya-model-publisher/badge.svg|Coverage Status on coveralls.io}} | [[https://coveralls.io/r/wearehoods/django-ya-model-publisher|coveralls.io/r/wearehoods/django-ya-model-publisher]] |

== Features

* Django CMS page support.
* Add request/reject buttons in Django CMS toolbar.
* Django CMS placeholders support.
* Hvad/Parler support.
* Restrict user access to publish functions with user permissions.


== base info

We have these three user types:

* A user with only a few rights (we call it **'reporter'**)
* A user with more rights (We call it **'editor'**)
* The superuser with all rights

The user case is following:

* **'reporter'**:
** can only change draft content
** can't change public content
** can't delete publisher model entries or CMS pages.
** can send a //(un-)publish request// to the 'editor' with a text node.

* **'editor'**:
** can response open publishing request from 'reporter'.
** can change drafts and public content, but only if there is no pending request.
** can delete publisher model entries or CMS pages.
** can't delete/manipulate publisher state model entries.


== permissions

Permissions for **'reporter'** who can only create //(un-)publish requests//:
{{{
...
[ ] cms.publish_page
...
[*] cms.add_page
[*] cms.change_page
[ ] cms.delete_page
...
[ ] publisher.add_publisherstatemodel
[*] publisher.change_publisherstatemodel
[ ] publisher.delete_publisherstatemodel
...
[ ] <app_name>.can_publish_<model_name>
...
[*] <app_name>.add_<model_name>
[*] <app_name>.change_<model_name>
[ ] <app_name>.delete_<model_name>
...
}}}


Permissions for **'editor'** who can //accept/reject (un-)publish requests//:
{{{
...
[*] cms.publish_page
...
[*] cms.add_page
[*] cms.change_page
[*] cms.delete_page
...
[ ] publisher.add_publisherstatemodel
[*] publisher.change_publisherstatemodel
[ ] publisher.delete_publisherstatemodel
...
[*] <app_name>.can_publish_<model_name>
...
[*] <app_name>.add_<model_name>
[*] <app_name>.change_<model_name>
[*] <app_name>.delete_<model_name>
...
}}}

**Important**: To prevent a privilege escalation, both users must **not** have access to these models:

* django.contrib.auth.models.Permission
* django.contrib.auth.models.Group
* cms.models.PagePermission

== Test users:

See user permission tests in:

* [[https://github.com/wearehoods/django-ya-model-publisher/blob/master/publisher_tests/test_basics.py|publisher_tests.test_basics.PermissionTestCase]]


== Primary key type compatibility

The {{{publisher.models.PublisherStateModel}}} used a  {{{PositiveIntegerField}}} for the {{{GenericForeignKey}}} so it can only be used for models with a integer primary keys!
See also: https://docs.djangoproject.com/en/1.11/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericForeignKey


== Django compatibility

|= django-ya-model-publisher |= django version      |= python            |
| >=v0.5.x                   | 1.8, 1.9, 1.10, 1.11 | 3.5, 3.6           |
| v0.4.x                     | 1.8, 1.9, 1.10, 1.11 | 2.7, 3.4, 3.5, 3.6 |

Note: See travis/tox config files for current test matrix


== run tests

run tests via //py.test// with current python/environment:
{{{
$ make test
or
$ ./setup.py test
or
$ python tests/manage.py test myapp
}}}

run test via //tox// e.g.:
{{{
$ make tox
or
$ ./setup.py tox
or
$ tox
}}}


=== run test project


You can run the test environment by:

{{{
$ ./run_test_project_dev_server.sh
}}}
or:
{{{
$ ./publisher_test_project/manage.py run_test_project_dev_server
}}}


The following steps will be executed:

* Create django users if not exists:
** A django **'superuser'**
** The user **editor**: He can accept/reject un-/publish requests
** The user **reporter**: He can create un-/publish requests
** note: Both users will used the same password as the 'superuser' !
* run migration
* insert test fixtures (Create Django CMS pages)
* collect static files
* run the django development server on localhost


You can pass arguments to the helper script, e.g.:
{{{
$ ./run_test_project_dev_server.sh --help
...
usage: manage.py run_test_project_dev_server [-h] [--version] [-v {0,1,2,3}]
                                             [--settings SETTINGS]
                                             [--pythonpath PYTHONPATH]
                                             [--traceback] [--no-color]
                                             [--ipv6] [--nothreading]
                                             [--noreload] [--nostatic]
                                             [--insecure]
                                             [addrport]
...
}}}


To 'reset' the test fixtures, run this:
{{{
$ ./publisher_test_project/manage.py create_test_data --fresh
}}}

For a complete fresh database, just remove the sqlite file, e.g.:
{{{
$ rm publisher_test_project/publisher_test_database.sqlite3
}}}


== Backwards-incompatible changes

=== v0.6.0

The permission names changed! Please update your django user permissions, too.

These permissions are removed:
* direct_publisher
* ask_publisher_request
* reply_publisher_request

Please read the information above.

== history

* v0.6.1 - 28.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.6.0...v0.6.1|compare v0.6.0...v0.6.1]]
** remove own "unique_together": Add {{{"publisher_is_draft"}}} to your own "unique_together" tuple
** remove out dated manage command "update_permissions" (can be found in [[https://github.com/jedie/django-tools|django-tools]])
* v0.6.0 - 27.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.5.1...v0.6.0|compare v0.5.1...v0.6.0]]
** refactor permissions and publisher workflow
** NEW: {{{publisher.views.PublisherCmsViewMixin}}}
** NEW: {{{publisher.admin.VisibilityMixin}}}
** bugfix django v1.11 compatibility
** Expand tests with {{{publisher_test_project.publisher_list_app}}}
* v0.5.1 - 20.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.5.0...v0.5.1|compare v0.5.0...v0.5.1]]
** fix python package (add missing parts)
** change travis/tox/pytest configuration
** minor code update
* v0.5.0 - 19.12.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.4.1...v0.5.0|compare v0.4.1...v0.5.0]]
** Skip official support for python v2.7 and v3.4 (remove from text matrix)
** Implement "request/reject/accept publishing" workflow with a shot messages and logging
** Add "request/reject/accept publishing" buttons to Django CMS toolbar for cms pages.
* v0.4.1 - 14.11.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.4.0.dev1...v0.4.1|compare v0.4.0.dev1...v0.4.1]]
** Refactor test run setup
** bugfix project name
* v0.4.0.dev1 - 14.11.2017 - [[https://github.com/wearehoods/django-ya-model-publisher/compare/v0.3.1...v0.4.0.dev1|compare v0.3.1...v0.4.0.dev1]]
** Just create the fork and apply all pull requests from [[https://github.com/andersinno/django-model-publisher-ai/pull/14|andersinno/django-model-publisher-ai/pull/14]]

== links ==

| Homepage      | http://github.com/wearehoods/django-ya-model-publisher
| PyPi.org      | https://pypi.org/project/django-ya-model-publisher/
| PyPi (legacy) | http://pypi.python.org/pypi/django-ya-model-publisher/


== donation ==

* [[https://www.paypal.me/JensDiemer|paypal.me/JensDiemer]]
* [[https://flattr.com/submit/auto?uid=jedie&url=https%3A%2F%2Fgithub.com%2Fwearehoods%2Fdjango-ya-model-publisher%2F|Flattr This!]]
* Send [[http://www.bitcoin.org/|Bitcoins]] to [[https://blockexplorer.com/address/1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F|1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F]]

{'fraction_non_alphanumeric': 0.154848832297387, 'fraction_numerical': 0.02781968499185324, 'mean_word_length': 3.441704636826588, 'pattern_counts': {'":': 2, '<': 35, '<?xml version=': 0, '>': 37, 'https://': 43, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5848427', 'n_tokens_mistral': 5891, 'n_tokens_neox': 5609, 'n_words': 1230}