Update Licenses available for add-on developers to choose from on AMO (#22818)

This commit is contained in:
Andrea Marchesini 2024-11-20 21:14:23 +01:00 коммит произвёл GitHub
Родитель b2e7ba47d6
Коммит 0c577c01a1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
12 изменённых файлов: 196 добавлений и 228 удалений

Просмотреть файл

@ -26,12 +26,16 @@ Open source license slugs are taken from the `SPDX License list <https://spdx.or
=================== ==============================================================
all-rights-reserved All Rights Reserved. This is not an open source license.
MPL-2.0 `Mozilla Public License 2.0 <https://www.mozilla.org/MPL/2.0/>`_
GPL-2.0-or-later `GNU General Public License v2.0 (or later) <https://www.gnu.org/licenses/gpl-2.0.html>`_
GPL-3.0-or-later `GNU General Public License v3.0 (or later) <https://www.gnu.org/licenses/gpl-3.0.html>`_
LGPL-2.1-or-later `GNU Lesser General Public License v2.1 (or later) <https://www.gnu.org/licenses/lgpl-2.1.html>`_
LGPL-3.0-or-later `GNU Lesser General Public License v3.0 (or later) <https://www.gnu.org/licenses/lgpl-3.0.html>`_
MIT `The MIT License <https://www.opensource.org/license/mit>`_
BSD-2-Clause `The 2-Clause BSD License <https://www.opensource.org/license/bsd-2-clause>`_
Apache-2.0 `Apache License 2.0 <https://spdx.org/licenses/Apache-2.0.html>`_
GPL-2.0-only `GNU General Public License v2.0 only <https://spdx.org/licenses/GPL-2.0-only.html>`_
GPL-3.0-only `GNU General Public License v3.0 only <https://spdx.org/licenses/GPL-3.0-only.html>`_
LGPL-2.1-only `GNU Lesser General Public License v2.1 only <https://spdx.org/licenses/LGPL-2.1-only.html>`_
LGPL-3.0-only `GNU Lesser General Public License v3.0 only <https://spdx.org/licenses/LGPL-3.0-only.html>`_
AGPL-3.0-only `GNU Affero General Public License v3.0 only <https://spdx.org/licenses/AGPL-3.0-only.html>`_
MIT `MIT License <https://spdx.org/licenses/MIT.html>`_
ISC `ISC License <https://spdx.org/licenses/ISC.html>`_
BSD-2-Clause `BSD 2-Clause "Simplified" License <https://spdx.org/licenses/BSD-2-Clause.html>`_
Unlicense `The Unlicense <https://spdx.org/licenses/Unlicense.html>`_
=================== ==============================================================

Просмотреть файл

@ -194,3 +194,6 @@ SWAGGER_SETTINGS = {
},
'PERSIST_AUTH': True,
}
# This is not a testing environment
TESTING_ENV = False

Просмотреть файл

@ -110,3 +110,6 @@ CINDER_QUEUE_PREFIX = 'amo-env-'
SOCKET_LABS_TOKEN = 'fake-test-token'
SOCKET_LABS_SERVER_ID = '12345'
SOCKET_LABS_HOST = 'https://fake-socketlabs.com/v1/'
# This is a testing environment
TESTING_ENV = True

Просмотреть файл

@ -54,7 +54,11 @@ from olympia.amo.tests import (
from olympia.amo.urlresolvers import get_outgoing_url
from olympia.bandwagon.models import Collection
from olympia.constants.categories import CATEGORIES
from olympia.constants.licenses import LICENSE_GPL3, LICENSES_BY_BUILTIN
from olympia.constants.licenses import (
LICENSE_COPYRIGHT_AR,
LICENSE_GPL3,
LICENSES_BY_BUILTIN,
)
from olympia.constants.promoted import RECOMMENDED
from olympia.files.models import WebextPermission
from olympia.promoted.models import PromotedAddon
@ -783,9 +787,9 @@ class AddonSerializerOutputTestMixin:
assert result['current_version']['license'] == {
'id': self.addon.current_version.license.pk,
'is_custom': False,
'name': {'en-US': 'GNU General Public License v3.0'},
'slug': 'GPL-3.0-or-later',
'url': 'https://www.gnu.org/licenses/gpl-3.0.html',
'name': {'en-US': 'GNU General Public License v3.0 only'},
'slug': 'GPL-3.0-only',
'url': 'https://spdx.org/licenses/GPL-3.0-only.html',
}
def test_categories_as_object(self):
@ -1277,7 +1281,7 @@ class TestVersionSerializerOutput(TestCase):
result = self.serialize()
assert 'is_custom' not in result['license']
license.update(builtin=11)
license.update(builtin=12)
result = self.serialize()
# Builtin licenses with no url shouldn't get the version license url.
assert result['license']['url'] is None
@ -1313,10 +1317,11 @@ class TestVersionSerializerOutput(TestCase):
addon = addon_factory()
self.version = addon.current_version
license = self.version.license
license.update(builtin=18)
assert license._constant == LICENSES_BY_BUILTIN[18]
license.update(builtin=LICENSE_COPYRIGHT_AR.builtin)
assert license._constant == LICENSES_BY_BUILTIN[LICENSE_COPYRIGHT_AR.builtin]
assert license._constant == LICENSE_COPYRIGHT_AR
builtin_license_name_english = str(LICENSES_BY_BUILTIN[18].name)
builtin_license_name_english = str(LICENSE_COPYRIGHT_AR.name)
result = LicenseSerializer(context={'request': self.request}).to_representation(
license
@ -1328,10 +1333,10 @@ class TestVersionSerializerOutput(TestCase):
# A request with no ?lang gets you the site default l10n in a dict to
# match how non-constant values are returned.
assert result['name'] == {'en-US': builtin_license_name_english}
assert result['url'] == LICENSES_BY_BUILTIN[18].url
assert result['url'] == LICENSE_COPYRIGHT_AR.url
with self.activate('de'):
builtin_license_name_german = str(LICENSES_BY_BUILTIN[18].name)
builtin_license_name_german = str(LICENSE_COPYRIGHT_AR.name)
result = LicenseSerializer(
context={'request': self.request}
@ -1344,10 +1349,10 @@ class TestVersionSerializerOutput(TestCase):
'de': builtin_license_name_german,
'en-US': builtin_license_name_english,
}
assert result['url'] == LICENSES_BY_BUILTIN[18].url
assert result['url'] == LICENSE_COPYRIGHT_AR.url
with self.activate('fr'):
builtin_license_name_french = str(LICENSES_BY_BUILTIN[18].name)
builtin_license_name_french = str(LICENSE_COPYRIGHT_AR.name)
# But a requested lang returns an object with the requested translation
lang_request = APIRequestFactory().get('/?lang=fr')
@ -1355,7 +1360,7 @@ class TestVersionSerializerOutput(TestCase):
license
)
assert result['name'] == {'fr': builtin_license_name_french}
assert result['url'] == LICENSES_BY_BUILTIN[18].url
assert result['url'] == LICENSE_COPYRIGHT_AR.url
# Make sure the license slug is not present in v3/v4
gates = {self.request.version: ('del-version-license-slug',)}

Просмотреть файл

@ -62,6 +62,7 @@ class Command(BaseDataCommand):
self.logger.info('Loading initial data...')
call_command('loaddata', 'initial.json')
call_command('import_prod_versions')
call_command('import_licenses')
call_command(
'createsuperuser',
'--no-input',

Просмотреть файл

@ -347,6 +347,7 @@ class BaseTestDataCommand(TestCase):
reindex = mock.call('reindex', '--wipe', '--force', '--noinput')
load_initial_data = mock.call('loaddata', 'initial.json')
import_prod_versions = mock.call('import_prod_versions')
import_licenses = mock.call('import_licenses')
createsuperuser = mock.call(
'createsuperuser',
'--no-input',
@ -805,6 +806,7 @@ class TestSeedDataCommand(BaseTestDataCommand):
self.mock_commands.migrate,
self.mock_commands.load_initial_data,
self.mock_commands.import_prod_versions,
self.mock_commands.import_licenses,
self.mock_commands.createsuperuser,
self.mock_commands.load_zadmin_users,
self.mock_commands.generate_addons('firefox', 10),

Просмотреть файл

@ -0,0 +1,15 @@
from django.core.management.base import BaseCommand
from olympia.constants.licenses import ALL_LICENSES
from olympia.versions.models import License
class Command(BaseCommand):
help = """Import a the licenses."""
def handle(self, *args, **options):
for license in ALL_LICENSES:
try:
License.objects.get_or_create(builtin=license.builtin)
except Exception:
continue

Просмотреть файл

@ -18,55 +18,73 @@ class LICENSE_MPL2(_LicenseBase):
slug = 'MPL-2.0'
class LICENSE_GPL2(_LicenseBase):
name = _('GNU General Public License v2.0')
url = 'https://www.gnu.org/licenses/gpl-2.0.html'
class LICENSE_APACHE2(_LicenseBase):
name = _('Apache License 2.0')
url = 'https://spdx.org/licenses/Apache-2.0.html'
builtin = 2
slug = 'GPL-2.0-or-later'
slug = 'Apache-2.0'
class LICENSE_GPL2(_LicenseBase):
name = _('GNU General Public License v2.0 only')
url = 'https://spdx.org/licenses/GPL-2.0-only.html'
builtin = 3
slug = 'GPL-2.0-only'
class LICENSE_GPL3(_LicenseBase):
name = _('GNU General Public License v3.0')
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
builtin = 3
slug = 'GPL-3.0-or-later'
name = _('GNU General Public License v3.0 only')
url = 'https://spdx.org/licenses/GPL-3.0-only.html'
builtin = 4
slug = 'GPL-3.0-only'
class LICENSE_LGPL2(_LicenseBase):
name = _('GNU Lesser General Public License v2.1')
url = 'https://www.gnu.org/licenses/lgpl-2.1.html'
builtin = 4
slug = 'LGPL-2.1-or-later'
name = _('GNU Lesser General Public License v2.1 only')
url = 'https://spdx.org/licenses/LGPL-2.1-only.html'
builtin = 5
slug = 'LGPL-2.1-only'
class LICENSE_LGPL3(_LicenseBase):
name = _('GNU Lesser General Public License v3.0')
url = 'https://www.gnu.org/licenses/lgpl-3.0.html'
builtin = 5
slug = 'LGPL-3.0-or-later'
name = _('GNU Lesser General Public License v3.0 only')
url = 'https://spdx.org/licenses/LGPL-3.0-only.html'
builtin = 6
slug = 'LGPL-3.0-only'
class LICENSE_AGPL3(_LicenseBase):
name = _('GNU Affero General Public License v3.0 only')
url = 'https://spdx.org/licenses/AGPL-3.0-only.html'
builtin = 7
slug = 'AGPL-3.0-only'
class LICENSE_MIT(_LicenseBase):
name = _('The MIT License')
url = 'https://www.opensource.org/license/mit'
builtin = 6
name = _('MIT License')
url = 'https://spdx.org/licenses/MIT.html'
builtin = 8
slug = 'MIT'
class LICENSE_ISC(_LicenseBase):
name = _('ISC License')
url = 'https://spdx.org/licenses/ISC.html'
builtin = 9
slug = 'ISC'
class LICENSE_BSD(_LicenseBase):
name = _('The 2-Clause BSD License')
url = 'https://www.opensource.org/license/bsd-2-clause'
builtin = 7
name = _('BSD 2-Clause "Simplified" License')
url = 'https://spdx.org/licenses/BSD-2-Clause.html'
builtin = 10
slug = 'BSD-2-Clause'
# builtin 8, 9 aren't used in any current versions, and aren't available for selection.
class LICENSE_MPL1(_LicenseBase):
name = _('Mozilla Public License 1.1')
url = 'https://www.mozilla.org/MPL/MPL-1.1.html'
builtin = 10
builtin = 11
slug = 'MPL-1.1'
on_form = False # obsolete and unavailable for selection
@ -75,7 +93,7 @@ class LICENSE_CC_COPYRIGHT(_LicenseBase):
name = _('All Rights Reserved')
icons = 'copyr'
url = None
builtin = 11
builtin = 12
creative_commons = True
slug = 'cc-all-rights-reserved'
@ -84,7 +102,7 @@ class LICENSE_CC_BY30(_LicenseBase):
name = _('Creative Commons Attribution 3.0')
icons = 'cc-attrib'
url = 'https://creativecommons.org/licenses/by/3.0/'
builtin = 12
builtin = 13
creative_commons = True
slug = 'CC-BY-3.0'
on_form = False
@ -94,7 +112,7 @@ class LICENSE_CC_BY_NC30(_LicenseBase):
name = _('Creative Commons Attribution-NonCommercial 3.0')
icons = 'cc-attrib cc-noncom'
url = 'https://creativecommons.org/licenses/by-nc/3.0/'
builtin = 13
builtin = 14
creative_commons = True
slug = 'CC-BY-NC-3.0'
on_form = False
@ -104,7 +122,7 @@ class LICENSE_CC_BY_NC_ND30(_LicenseBase):
name = _('Creative Commons Attribution-NonCommercial-NoDerivs 3.0')
icons = 'cc-attrib cc-noncom cc-noderiv'
url = 'https://creativecommons.org/licenses/by-nc-nd/3.0/'
builtin = 14
builtin = 15
creative_commons = True
slug = 'CC-BY-NC-ND-3.0'
on_form = False
@ -114,7 +132,7 @@ class LICENSE_CC_BY_NC_SA30(_LicenseBase):
name = _('Creative Commons Attribution-NonCommercial-Share Alike 3.0')
icons = 'cc-attrib cc-noncom cc-share'
url = 'https://creativecommons.org/licenses/by-nc-sa/3.0/'
builtin = 15
builtin = 16
creative_commons = True
slug = 'CC-BY-NC-SA-3.0'
on_form = False
@ -124,7 +142,7 @@ class LICENSE_CC_BY_ND30(_LicenseBase):
name = _('Creative Commons Attribution-NoDerivs 3.0')
icons = 'cc-attrib cc-noderiv'
url = 'https://creativecommons.org/licenses/by-nd/3.0/'
builtin = 16
builtin = 17
creative_commons = True
slug = 'CC-BY-ND-3.0'
on_form = False
@ -134,20 +152,12 @@ class LICENSE_CC_BY_SA30(_LicenseBase):
name = _('Creative Commons Attribution-ShareAlike 3.0')
icons = 'cc-attrib cc-share'
url = 'https://creativecommons.org/licenses/by-sa/3.0/'
builtin = 17
builtin = 18
creative_commons = True
slug = 'CC-BY-SA-3.0'
on_form = False
class LICENSE_COPYRIGHT_AR(_LicenseBase):
name = _('All Rights Reserved')
icons = 'copyr'
url = None
builtin = 18
slug = 'all-rights-reserved'
class LICENSE_CC_BY40(_LicenseBase):
name = _('Creative Commons Attribution 4.0')
icons = 'cc-attrib'
@ -208,6 +218,21 @@ class LICENSE_CC_BY_SA40(_LicenseBase):
on_form = True
class LICENSE_UNLICENSE(_LicenseBase):
name = _('The Unlicense')
url = 'https://spdx.org/licenses/Unlicense.html'
builtin = 25
slug = 'Unlicense'
class LICENSE_COPYRIGHT_AR(_LicenseBase):
name = _('All Rights Reserved')
icons = 'copyr'
url = None
builtin = 26
slug = 'all-rights-reserved'
ALL_LICENSES = (
LICENSE_MPL1,
LICENSE_MPL2,
@ -231,6 +256,10 @@ ALL_LICENSES = (
LICENSE_CC_BY_ND40,
LICENSE_CC_BY_SA40,
LICENSE_COPYRIGHT_AR,
LICENSE_APACHE2,
LICENSE_AGPL3,
LICENSE_ISC,
LICENSE_UNLICENSE,
)
LICENSES_BY_BUILTIN = {license.builtin: license for license in ALL_LICENSES}
CC_LICENSES = {

Просмотреть файл

@ -167,7 +167,7 @@ class TestEditLicense(TestOwnership):
assert response.status_code == 302
def test_success_add_builtin(self):
data = self.build_form_data({'builtin': 7})
data = self.build_form_data({'builtin': LICENSE_BSD.builtin})
response = self.client.post(self.url, data)
assert response.status_code == 302
assert self.license == self.get_version().license

Просмотреть файл

@ -1836,7 +1836,7 @@ class TestStaticThemeSubmitDetails(DetailsPageMixin, TestSubmitBase):
}
)
cat_form = {'categories': [300]}
license_form = {'license-builtin': 11}
license_form = {'license-builtin': LICENSE_CC_COPYRIGHT.builtin}
result.update(describe_form)
result.update(cat_form)
result.update(license_form)
@ -1922,7 +1922,9 @@ class TestStaticThemeSubmitDetails(DetailsPageMixin, TestSubmitBase):
)
def test_set_builtin_license_no_log(self):
self.is_success(self.get_dict(**{'license-builtin': 11}))
self.is_success(
self.get_dict(**{'license-builtin': LICENSE_CC_COPYRIGHT.builtin})
)
addon = self.get_addon()
assert addon.status == amo.STATUS_NOMINATED
assert addon.current_version.license.builtin == LICENSE_CC_COPYRIGHT.builtin

Просмотреть файл

@ -1,169 +1,4 @@
[
{
"pk": 1,
"model": "versions.license",
"fields": {
"name": 1,
"created": "2009-04-30T23:48:48",
"text": null,
"modified": "2010-10-14T16:14:13",
"builtin": 3
}
},
{
"pk": 2,
"model": "versions.license",
"fields": {
"name": 2,
"created": "2009-05-01T04:53:42",
"text": null,
"modified": "2010-10-14T16:14:13",
"builtin": 5
}
},
{
"pk": 3,
"model": "versions.license",
"fields": {
"name": 3,
"created": "2009-05-01T05:00:44",
"text": null,
"modified": "2010-10-14T16:14:14",
"builtin": 2
}
},
{
"pk": 4,
"model": "versions.license",
"fields": {
"name": 4,
"created": "2009-05-01T08:02:14",
"text": null,
"modified": "2010-10-14T16:14:14",
"builtin": 4
}
},
{
"pk": 5,
"model": "versions.license",
"fields": {
"name": 5,
"created": "2009-05-01T08:36:09",
"text": null,
"modified": "2010-10-14T16:14:15",
"builtin": 7
}
},
{
"pk": 6,
"model": "versions.license",
"fields": {
"name": 6,
"created": "2009-05-01T17:29:25",
"text": null,
"modified": "2010-10-14T16:14:15",
"builtin": 6
}
},
{
"pk": 7,
"model": "versions.license",
"fields": {
"name": 7,
"created": "2013-04-16T14:12:38",
"text": null,
"modified": "2013-04-16T14:12:38",
"builtin": 1
}
},
{
"pk": 8,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 11
}
},
{
"pk": 9,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 12
}
},
{
"pk": 10,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 13
}
},
{
"pk": 11,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 14
}
},
{
"pk": 12,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 1
}
},
{
"pk": 13,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 16
}
},
{
"pk": 14,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 17
}
},
{
"pk": 15,
"model": "versions.license",
"fields": {
"name": null,
"created": "2018-01-01T00:00:00",
"text": null,
"modified": "2018-01-01T00:00:00",
"builtin": 15
}
},
{
"pk": 1,
"model": "translations.translation",

Просмотреть файл

@ -0,0 +1,69 @@
# Generated by Django 4.2.16 on 2024-11-01 09:30
from django.db import migrations
from django.conf import settings
from olympia.constants.licenses import *
BUILTIN_MAP = [
# (License object, previous builtin, new builtin)
(LICENSE_GPL2, 2, 3),
(LICENSE_GPL3, 3, 4),
(LICENSE_LGPL2, 4, 5),
(LICENSE_LGPL3, 5, 6),
(LICENSE_MIT, 6, 8),
(LICENSE_BSD, 7, 10),
(LICENSE_MPL1, 10, 11),
(LICENSE_CC_COPYRIGHT, 11, 12),
(LICENSE_CC_BY30, 12, 13),
(LICENSE_CC_BY_NC30, 13, 14),
(LICENSE_CC_BY_NC_ND30, 14, 15),
(LICENSE_CC_BY_NC_SA30, 15, 16),
(LICENSE_CC_BY_ND30, 16, 17),
(LICENSE_CC_BY40, 17, 18),
(LICENSE_COPYRIGHT_AR, 18, 26),
]
def set_new_builtins(apps, schema_editor):
License = apps.get_model('versions', 'License')
for i in reversed(BUILTIN_MAP):
try:
# not all the licenses exist. If not, we skip it.
license = License.objects.get(builtin=i[1])
except:
continue
if license.builtin != i[0].builtin:
license.update(builtin=i[2])
if settings.TESTING_ENV == False:
for license in ALL_LICENSES:
try:
License.objects.get_or_create(builtin=license.builtin)
except Exception:
continue
def restore_old_builtins(apps, schema_editor):
License = apps.get_model('versions', 'License')
for i in BUILTIN_MAP:
try:
# not all the licenses exist. If not, we skip it.
license = License.objects.get(builtin=i[2])
except:
continue
if license.builtin != i[0].builtin:
license.update(builtin=i[1])
class Migration(migrations.Migration):
dependencies = [
('versions', '0046_auto_20240916_1240'),
]
operations = [
migrations.RunPython(set_new_builtins, restore_old_builtins),
]