{"id":26482017,"url":"https://github.com/kiwitcms/tenants","last_synced_at":"2025-08-22T14:12:10.184Z","repository":{"id":34463704,"uuid":"177972150","full_name":"kiwitcms/tenants","owner":"kiwitcms","description":"Multi-tenant support for Kiwi TCMS","archived":false,"fork":false,"pushed_at":"2025-08-21T14:35:09.000Z","size":417,"stargazers_count":10,"open_issues_count":4,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-21T14:35:42.401Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://kiwitcms.org","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kiwitcms.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"custom":["https://kiwitcms.org/#subscriptions"],"github":["kiwitcms"],"patreon":null,"open_collective":"kiwitcms","ko_fi":null,"tidelift":"pypi/kiwitcms","community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null}},"created_at":"2019-03-27T10:35:16.000Z","updated_at":"2025-08-21T14:35:09.000Z","dependencies_parsed_at":"2024-01-13T23:20:15.814Z","dependency_job_id":"5f29c266-5828-47dd-bfa7-64d5ab4c143b","html_url":"https://github.com/kiwitcms/tenants","commit_stats":{"total_commits":469,"total_committers":11,"mean_commits":42.63636363636363,"dds":0.4541577825159915,"last_synced_commit":"d4c63a565614f36e8c089fc07e138e323da15a3c"},"previous_names":[],"tags_count":70,"template":false,"template_full_name":null,"purl":"pkg:github/kiwitcms/tenants","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwitcms%2Ftenants","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwitcms%2Ftenants/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwitcms%2Ftenants/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwitcms%2Ftenants/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kiwitcms","download_url":"https://codeload.github.com/kiwitcms/tenants/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwitcms%2Ftenants/sbom","scorecard":{"id":562144,"data":{"date":"2025-08-11","repo":{"name":"github.com/kiwitcms/tenants","commit":"a4b6fd0546af177b0cda4657794853263424be44"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.7,"checks":[{"name":"Code-Review","score":1,"reason":"Found 2/16 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:14","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:15","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Warn: no topLevel permission defined: .github/workflows/testing.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/testing.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/testing.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/testing.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/testing.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/testing.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/kiwitcms/tenants/testing.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/testing.yml:38","Warn: pipCommand not pinned by hash: .github/workflows/testing.yml:39","Warn: pipCommand not pinned by hash: .github/workflows/testing.yml:41","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   3 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Affero General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/kiwitcms/.github/SECURITY.md:1","Info: Found linked content: github.com/kiwitcms/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/kiwitcms/.github/SECURITY.md:1","Info: Found text in security policy: github.com/kiwitcms/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":9,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 21 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T14:01:38.414Z","repository_id":34463704,"created_at":"2025-08-20T14:01:38.415Z","updated_at":"2025-08-20T14:01:38.415Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271650860,"owners_count":24796725,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-22T02:00:08.480Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-20T03:36:39.125Z","updated_at":"2025-08-22T14:12:10.174Z","avatar_url":"https://github.com/kiwitcms.png","language":"Python","funding_links":["https://kiwitcms.org/#subscriptions","https://github.com/sponsors/kiwitcms","https://opencollective.com/kiwitcms","https://tidelift.com/funding/github/pypi/kiwitcms","https://tidelift.com/badges/package/pypi/kiwitcms-tenants","https://tidelift.com/subscription/pkg/pypi-kiwitcms-tenants?utm_source=pypi-kiwitcms-tenants\u0026utm_medium=github\u0026utm_campaign=readme"],"categories":[],"sub_categories":[],"readme":"Multi-tenant support for Kiwi TCMS\n==================================\n\n.. image:: https://travis-ci.org/kiwitcms/tenants.svg?branch=master\n    :target: https://travis-ci.org/kiwitcms/tenants\n\n.. image:: https://coveralls.io/repos/github/kiwitcms/tenants/badge.svg?branch=master\n   :target: https://coveralls.io/github/kiwitcms/tenants?branch=master\n\n.. image:: https://pyup.io/repos/github/kiwitcms/tenants/shield.svg\n    :target: https://pyup.io/repos/github/kiwitcms/tenants/\n    :alt: Python updates\n\n.. image:: https://tidelift.com/badges/package/pypi/kiwitcms-tenants\n    :target: https://tidelift.com/subscription/pkg/pypi-kiwitcms-tenants?utm_source=pypi-kiwitcms-tenants\u0026utm_medium=github\u0026utm_campaign=readme\n    :alt: Tidelift\n\n.. image:: https://opencollective.com/kiwitcms/tiers/sponsor/badge.svg?label=sponsors\u0026color=brightgreen\n   :target: https://opencollective.com/kiwitcms#contributors\n   :alt: Become a sponsor\n\n.. image:: https://img.shields.io/twitter/follow/KiwiTCMS.svg\n    :target: https://twitter.com/KiwiTCMS\n    :alt: Kiwi TCMS on Twitter\n\n\nIntroduction\n------------\n\nThis package provides multi-tenant support for Kiwi TCMS and is a wrapper\naround `django-tenants \u003chttps://github.com/tomturner/django-tenants\u003e`_.\nYou can use it to host different organizations on the same application server or host\nmultiple product instances used by different teams. Each tenant is able to see\nonly the information created by themselves.\n\n\nInstallation\n------------\n\n**IMPORTANT:** multi-tenancy is backed by PostgreSQL schemas! It will not work\nwith a different database backend.\n\n**WARNING:** current tenant is decided based on the FQDN by which you\nare accessing Kiwi TCMS!\n\nThe following changes need to be introduced into a downstream Docker image or\nyour Python virtualenv where the main Kiwi TCMS instance is hosted::\n\n    pip install kiwitcms-tenants\n\nthen make sure ``KIWI_TENANTS_DOMAIN`` ENV variable is specified !!!\nThe rest of the settings are installed into ``tcms_settings_dir/multi_tenant.py``\nand Kiwi TCMS will pick them up automatically!\n\n\nFirst boot configuration\n------------------------\n\nWhen starting your multi-tenant Kiwi TCMS instance for the first time you also\nneed to create information about the so called public tenant. That is the\ndefault tenant on which your application runs::\n\n    ./manage.py initial_setup\n\nYour tenant will be available at https://$KIWI_TENANTS_DOMAIN!\nOther tenants can be created via the web interface and will be available\nunder team-01.$KIWI_TENANTS_DOMAIN, product-02.$KIWI_TENANTS_DOMAIN, etc\ndepnding on the actual ``schema name`` you give them.\n\n\nDNS configuration\n-----------------\n\nYou need wildcard DNS resolution to be configured for ``*.tenants.example.org``!\n\nIf using AWS Route 53 create an A record with ``Name==*.tenants`` for the\n``example.org`` domain and point it to the IP address of your Kiwi TCMS instance.\n\nOnce DNS has been configured you should be able to query for various domains with\ntools like ``dig`` and ``nslookup``::\n\n    $ dig public.tenant.kiwitcms.org\n    ; \u003c\u003c\u003e\u003e DiG 9.11.4-P2-RedHat-9.11.4-12.P2.el7 \u003c\u003c\u003e\u003e public.tenant.kiwitcms.org\n    ;; global options: +cmd\n    ;; Got answer:\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: 58543\n    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1\n\n    ;; OPT PSEUDOSECTION:\n    ; EDNS: version: 0, flags:; udp: 4096\n    ;; QUESTION SECTION:\n    ;public.tenant.kiwitcms.org.    IN      A\n\n    ;; ANSWER SECTION:\n    public.tenant.kiwitcms.org. 36  IN      A       100.24.231.234\n\n    ;; Query time: 35 msec\n    ;; SERVER: 10.38.5.26#53(10.38.5.26)\n    ;; WHEN: Tue Nov 19 14:04:09 EET 2019\n    ;; MSG SIZE  rcvd: 71\n\n\n    $ nslookup linux.tenant.kiwitcms.org\n    Server:         10.38.5.26\n    Address:        10.38.5.26#53\n\n    Non-authoritative answer:\n    Name:   linux.tenant.kiwitcms.org\n    Address: 100.24.231.234\n\n\nAll sub-domains should resolve to the same IP address!\n\n\nMigrating Single-Tenant to Multi-Tenant\n---------------------------------------\n\nSee `Migrating Single-Tenant to Multi-Tenant\n\u003chttps://django-tenants.readthedocs.io/en/latest/use.html#migrating-single-tenant-to-multi-tenant\u003e`_\nsection in the official django-tenants documentation! It has been contributed by the Kiwi TCMS\nteam and that was the procedure we've used to migrate the previous demo website (ST) to\nits new MT version!\n\n\nLocal Development\n-----------------\n\nStarting with Kiwi TCMS v13.1 session and CSRF cookies are configured only on HTTPS\nconnections which will prevent browsers from sending cookies over a plain text HTTP\nconnection. This will result in not being able to login if you are using a local\ndevelopment server. To workaround this issue, first generate an SSL certificate::\n\n    /usr/bin/sscg -v -f --country BG --locality Sofia --organization \"Kiwi TCMS\" --organizational-unit \"QA\" --ca-file ssl/ca.crt --cert-file ssl/host.crt --cert-key-file ssl/host.key\n\nThen use the ``runerver_plus`` command to start Kiwi TCMS development server with HTTPS::\n\n    PYTHONPATH=../Kiwi/ KIWI_TENANTS_DOMAIN=tenant.example.bg ./manage.py runserver_plus --cert-file ssl/host.crt  --key-file ssl/host.key\n\nThen point your browser to https://tenant.example.bg:8000/.\nThe SSL warning from the browser is expected!\n\nYou can use your `OS hosts file \u003chttps://en.wikipedia.org/wiki/Hosts_(file)\u003e`_\nto configure DNS resolution during development::\n\n    127.0.0.1   localhost tenant.example.bg empty.tenant.example.bg\n\n\nChangelog\n---------\n\nv4.1.0 (09 Apr 2025)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add the ``tcms_tenants.email_validators.blacklist_non_authorized`` function\n  which prevents sending emails to non-authorized addresses!\n  IMPORTANT: this must be explictly configured via the ``EMAIL_VALIDATORS``\n  setting in order to take effect!\n\n\nv4.0.0 (06 Jan 2025)\n~~~~~~~~~~~~~~~~~~~~\n\n- Remove the ``DEFAULT_FILE_STORAGE`` setting and replace it with\n  ``STORAGES[\"default\"][\"BACKEND\"]`` for Django 5.1 compatibility\n- Add test case for default storage class\n\n\nv3.2.2 (11 Dec 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Show the 'Tenant expires' message in the last 24 hrs\n  to minimize annoyance\n\n\nv3.2.1 (12 Oct 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update email template for invited users\n\n\nv3.2.0 (28 Aug 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.6.1 to 3.7.0\n\n\nv3.1.0 (02 Jul 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add context processor for the ``TENANT_SCHEMA_NAME`` template variable\n- Update test suite for changes related to Django 5\n\n\nv3.0.0 (09 Jun 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Relicense this package under GNU Affero General Public License v3 or later\n- Prior versions are still licensed under GNU General Public License v3\n\n\nv2.8.3 (02 May 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Make sure to populate the ``extra_emails`` field when cloning a tenant\n\n\nv2.8.2 (01 May 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Allow downstream installations to override Edit tenant page template\n\n\nv2.8.1 (29 Apr 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Bug-fix: display empty string instead of ``None`` on Invite users page\n- Add test for utils function with an email which won't validate according to\n  ``settings.EMAIL_VALIDATORS``\n\n\nv2.8.0 (28 Apr 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Refactor HTML template for Invite Users page to display form field errors\n- When inviting users validate addresses taking into account the value of\n  ``settings.EMAIL_VALIDATORS``\n- Updated documentation\n- Adjust tests for newer version of django-grappelli\n\n\nv2.7.0 (24 Apr 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add the ``Tenant.extra_emails`` field for storing information like\n  technical email, billing email, etc. To be used by add-on tools\n- Add the ``initialize_tenants`` management command\n- Update local development instructions\n- Enable code formatting with ``black``\n- Start testing using upstream Postgres container\n- Execute CodeQL on pull request and branches\n- Adjust tests for Django 5.0\n\n\nv2.6.1 (08 Mar 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Remove use of ``non-existing.png`` file in tenant name area\n  to avoid 404 responses which trigger rate limiting\n\n\nv2.6.0 (14 Jan 2024)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.5.0 to 3.6.1\n- Update pylint-django from 2.5.3 to 2.5.5\n- Start building and testing with Python 3.11\n- Start testing with psycopg3\n\n\nv2.5.2 (24 Oct 2023)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add ``trackers_integration`` into ``tenant_groups.models.Group.relevant_apps``\n  to allow per-tenant assignment for permissions around personal API\n  tokens, see https://github.com/kiwitcms/trackers-integration/pull/44\n\n\nv2.5.1 (12 May 2023)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update to django-tenants==3.5.0\n- Replace ``form_errors_to_list()`` which was removed in Kiwi TCMS v12.2\n\n\nv2.5.0 (10 Feb 2023)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update to django-tenants==3.4.8\n- Bug fix on Create Tenant page for Kiwi TCMS v11.7 or later\n\n\nv2.4.0 (15 Nov 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Allow customization of tenant logo in navigation (Ivajlo Karabojkov)\n- Add CodeQL workflow for GitHub code scanning\n- Fix make messages command\n\n\nv2.3.2 (31 Oct 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.4.5 to 3.4.7\n- Don't add users to TenantGroup on ``empty`` tenant\n- Adjust redirects from Tenant admin page to avoid confusion\n- Update docs for initial configuration\n- Add more assertions into test\n\n\nv2.3.1 (10 Sep 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Don't access ``request.tenant`` if such attribute does not exist. Fixes\n  `KIWI-TCMS-K2 \u003chttps://sentry.io/organizations/kiwitcms/issues/3565864401/\u003e`_\n\n\nv2.3.0 (02 Sep 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Don't grant ``auth.view_`` permissions even on publicly readable tenants\n- Honor ``settings.DEFAULT_GROUPS`` instead of hard-coding. Invited users and\n  users authorized via the Admin panel will be added to tenant groups which\n  match ``settings.DEFAULT_GROUPS`` (\"Tester\" by default) if such tenant groups\n  exist. If the setting is an empty list or there are no tenant groups matching\n  the specific names configured then authorized users will be left without\n  group associations. It will be up to a Kiwi TCMS administrator to\n  manually assign permissions and tenant groups for each user.\n\n\nv2.2.1 (30 Aug 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Fix a bug in the ``create_oss_tenant()`` helper function\n\n\nv2.2.0 (14 Aug 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.4.2 to 3.4.4\n- Show tenant information in navigation (Ivajlo Karabojkov)\n- Allow editing Tenant.name to make it easier for admins to customize the\n  text shown in navigation!\n- Internal updates around testing and CI\n\n\nv2.1.1 (27 Apr 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Don't crash if user can't change tenant groups. Fixes\n  `KIWI-TCMS-J8 \u003chttps://sentry.io/organizations/kiwitcms/issues/3230191406/\u003e`_\n\n\nv2.1.0 (27 Apr 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add ``refresh_tenant_permissions`` command which will be executed automatically\n  by ``refresh_permissions``\n\n\nv2.0.1 (19 Apr 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Fix URL is help message\n\n\nv2.0.0 (18 Apr 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Define per-tenant ``Group`` model and add an authentication backend which will\n  consume permissions from tenant-groups. Closes #104\n  `Issue #104 \u003chttps://github.com/kiwitcms/tenants/issues/104\u003e`_\n- Add pre-commit CI config \u0026 apply automatic fixes\n\n\nv1.11.0 (24 Jan 2022)\n~~~~~~~~~~~~~~~~~~~~~\n\n- Add System check for ``KIWI_TENANTS_DOMAIN`` environment variable. Closes\n  `Issue #140 \u003chttps://github.com/kiwitcms/tenants/issues/140\u003e`_\n\n\nv1.10.0 (19 Jan 2022)\n~~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.4.1 to 3.4.2,\n  will help with migration to Django 4\n\n\nv1.9.0 (10 Jan 2022)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.3.4 to 3.4.1\n- Update expected error message for tests\n- Fix code coverage uploads\n\n\nv1.8.0 (16 Oct 2021)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.3.2 to 3.3.4. Fixes a bug for cloning tenants\n  when DB username contains a dash\n- Use f-strings b/c pylint really loves them\n\n\nv1.7.0 (03 Sep 2021)\n~~~~~~~~~~~~~~~~~~~~\n\n- Faster tenant creation with ``clone_tenant``. Fixes\n  `Issue #127 \u003chttps://github.com/kiwitcms/tenants/issues/127\u003e`_\n  Requires a schema with name ``empty`` to be present!\n- Fix pylint warnings\n- Migrate from Travis CI to GitHub Actions\n\n\nv1.6.0 (18 Jun 2021)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.3.1 to 3.3.2\n- More robust tenant domain detection to avoid bugs in the case where\n  public tenant's domain doesn't use a prefix (e.g. matches KIWI_TENANTS_DOMAIN)\n\n\nv1.5.0 (04 Jun 2021)\n~~~~~~~~~~~~~~~~~~~~\n\n- Database: Rename ``Tenant.on_trial`` -\u003e ``Tenant.publicly_readable``\n- Allow unauthorized users to access publicly readable tenants\n- Update django-tenants from 3.3.0 to 3.3.1\n- Update translation strings\n- Tested with Kiwi TCMS v10.1\n- Convert ``NewTenantForm`` to inherit from ``ModelForm``\n\n\nv1.4.4 (12 May 2021)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.2.1 to 3.3.0\n- Tested with Kiwi TCMS v10.0\n- Tested with Python 3.8\n\n\nv1.4.3 (25 Jan 2021)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add missing csrf_token in NewTenantForm\n\n\nv1.4.2 (23 Dec 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Fix a bug with how we override captcha field in user registration form\n- Fix invitation email subject\n\n\nv1.4 (23 Dec 2020)\n~~~~~~~~~~~~~~~~~~\n\n- Tested with Kiwi TCMS v8.9\n- Add warning for ``owner_id`` in README\n- Replace ModelChoiceField with UserField. Fixes\n  `Issue #114 \u003chttps://github.com/kiwitcms/tenants/issues/114\u003e`_\n- Support user invitions for tenant. Fixes\n  `Issue #116 \u003chttps://github.com/kiwitcms/tenants/issues/116\u003e`_\n\n\nv1.3.1 (09 Sep 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Replace deprecated import to silence warnings with Django 3.1\n\n\nv1.3 (26 Aug 2020)\n~~~~~~~~~~~~~~~~~~\n\n- Tested with Kiwi TCMS v8.6\n- Update django-tenants from 3.1.0 to 3.2.1\n- Don't pin dependencies in devel.txt\n\n\nv1.2.1 (24 Jul 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Filter out AuthorizedUsersChangeForm even on errors\n- Tested with Kiwi TCMS v8.5\n\n\nv1.2 (20 Jun 2020)\n~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.0.3 to 3.1.0\n- Improvements in tests and minor updates to make linters happy\n- Tested with Kiwi TCMS v8.4\n\n\nv1.1.1 (27 Apr 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Do not ship ``TENANT_APPS`` b/c it is distributed with Kiwi TCMS v8.3\n\n\nv1.1 (25 Apr 2020)\n~~~~~~~~~~~~~~~~~~\n\n- Bring back an improved HTML placeholder for schema_name\n- Properly validate input values for schema/domain names\n\n\nv1.0.3 (24 Apr 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Always lower case schema_name to make sure it can actually be\n  used as a valid hostname\n\n\nv1.0.2 (24 Apr 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.0.1 to 3.0.3\n- Show valid schema_name pattern as help text in UI\n- Remove schema_name placeholder text because it was misleading\n\n\nv1.0.1 (18 Mar 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Slightly adjust default values for settings ``TENANT_APPS`` and\n  ``MULTITENANT_RELATIVE_MEDIA_ROOT`` to match Kiwi TCMS and installations\n  prior to turning this package into a plugin. This will avoid dusrupting\n  existing deployments!\n\n\nv1.0 (15 Mar 2020)\n~~~~~~~~~~~~~~~~~~\n\n- Turn into proper Kiwi TCMS plugin and install settings overrides under\n  ``tcms_settings_dir/`` (compatible with Kiwi TCMS v8.2 or later)\n\n  - does not need ``MENU_ITEMS`` and ``ROOT_URLCONF`` override anymore\n  - does not need to load ``tcms_tenants`` in ``INSTALLED_APPS`` manually\n  - only need to specify ``KIWI_TENANTS_DOMAIN`` env variable!\n- Require ``tcms_tenants.add_tenant`` permission for ``NewTenantView``\n- Reimplement ``NewTenantView`` as ``FormView``\n- Refactor ``redirect_to()`` to class based view\n- Add tests for admin.py. Closes #5\n  `Issue #5 \u003chttps://github.com/kiwitcms/tenants/issues/5\u003e`_\n- Replace ``datetime.now`` with ``timezone.now`` for better support of\n  installations with enabled timezone config\n- Enable pylint. Closes\n  `Issue #17 \u003chttps://github.com/kiwitcms/tenants/issues/17\u003e`_\n- Enable flake8\n\n\nv0.5.1 (17 Feb 2020)\n~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants from 3.0.0 to 3.0.1. Fixes\n  `Issue #60 \u003chttps://github.com/kiwitcms/tenants/issues/60\u003e`_\n\n\nv0.5 (16 Jan 2020)\n~~~~~~~~~~~~~~~~~~\n\n- Bump django-tenants from 2.2.3 to 3.0.0\n- Tested successfully against Kiwi TCMS v7.3 with Django 3.0\n\n\nv0.4.7 (11 Dec 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Set ``tcms_tenants.tests.LoggedInTestCase.tenant.owner.password`` to\n  \"password\" so it can be reused by downstream tests\n\n\nv0.4.6 (11 Dec 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- New translations for Slovenian\n- Replace ugettext_lazy with gettext_lazy for Django 3.0\n- Start shipping ``tcms_tenants.tests`` to be used by other multi-tenant\n  add-on packages\n- Confirmed working against Kiwi TCMS v7.2\n\n\nv0.4.5 (24 Nov 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Document how to configure multi-tenancy\n- Document ST to MT migration\n- Add helper method ``create_oss_tenant()``\n- Internal updates to ``TENANT_APPS`` while testing\n\n\nv0.4.4 (29 Oct 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- New translations for Russian\n\n\nv0.4.3 (18 May 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Add ``Tenant.organization`` field\n- When creating tenant set site.name to tenant.domain.domain\n\n\nv0.4.0 (12 May 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Allow overriding create tenant form URL via additional\n  context variable named ``form_action_url``\n\n\nv0.3.0 (08 May 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Send email when a new tenant is created\n- Add middleware which can be used to block unpaid tenants\n- Rewrite middleware without deprecated ``MiddlewareMixin``, Refers to\n  `Issue #17 \u003chttps://github.com/kiwitcms/tenants/issues/17\u003e`_\n- Add more tests\n\nv0.2.0 (05 May 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Remove ``django.contrib.contenttypes`` from ``TENANT_APPS``\n- Make it easier to override ``NewTenantView``\n- Use ``DateTimeField`` instead of ``DateField``\n- Show first primary domain in Admin\n- Massive speed up tests\n- Pylint fixes\n\n\nv0.1.10 (03 May 2019)\n~~~~~~~~~~~~~~~~~~~~~\n\n- Bring back ``tenant_url`` template tag with optional\n  ``schema_name`` parameter\n\n\nv0.1.9 (03 May 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Fix failing tests\n\n\nv0.1.8 (03 May 2019)\n~~~~~~~~~~~~~~~~~~~~\n\n- Fix packaging for missing migrations directory\n- Add view which facilitates GitHub login \u0026 redirects.\n  Callers are supposed to perform OAuth login via public tenant and then\n  redirect to this view which will send the browser to the actual tenant!\n  This will resolve problems with ``redirect_uri`` mismatch that we're\n  seeing from GitHub b/c you can only specify one redirect uri\n- pylint fixes\n- Remove unused ``templatetags/`` directory\n\n\nv0.1.6 (28 April 2019)\n~~~~~~~~~~~~~~~~~~~~~~\n\n- Tenant object now has an owner\n\n\nv0.1.5 (24 April 2019)\n~~~~~~~~~~~~~~~~~~~~~~\n\n- Update django-tenants to 2.2.3\n- New translations for Slovenian\n- Don't ship ``test_project/`` files in wheel package\n\n\nv0.1.4 (15 April 2019)\n~~~~~~~~~~~~~~~~~~~~~~\n\n- Update to django-tenants 2.2.0 for Django 2.2 support\n\n\nv0.1.3 (10 April 2019)\n~~~~~~~~~~~~~~~~~~~~~~\n\n- Rename setting ``TCMS_TENANTS_DOMAIN`` to ``KIWI_TENANTS_DOMAIN``\n\n\nv0.1.2 (04 April 2019) - initial release\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- Support creating of tenants via web interface\n- Support for deleting tenants only by super-user\n- Support for authorizing other users to access the current tenant\n- Middleware which returns 403 Forbidden when non-authorized user\n  tries to access a tenant\n- Support for overriding the ``tcms_tenants/new.html`` template to\n  provide SLA, terms and conditions, etc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkiwitcms%2Ftenants","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkiwitcms%2Ftenants","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkiwitcms%2Ftenants/lists"}