Skip to content

Commit

Permalink
Update Licenses available for add-on developers to choose from on AMO
Browse files Browse the repository at this point in the history
  • Loading branch information
bakulf committed Nov 15, 2024
1 parent 03fae81 commit fe5a4e8
Show file tree
Hide file tree
Showing 12 changed files with 195 additions and 228 deletions.
16 changes: 10 additions & 6 deletions docs/topics/api/licenses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`_
=================== ==============================================================


Expand Down
3 changes: 3 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,6 @@ def insert_debug_toolbar_middleware(middlewares):
},
'PERSIST_AUTH': True,
}

# This is not a testing environment
TESTING_ENV = False
3 changes: 3 additions & 0 deletions settings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,6 @@
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
31 changes: 18 additions & 13 deletions src/olympia/addons/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@
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
Expand Down Expand Up @@ -783,9 +787,9 @@ def test_current_version_license_builtin(self):
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):
Expand Down Expand Up @@ -1277,7 +1281,7 @@ def test_license_no_url(self):
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
Expand Down Expand Up @@ -1313,10 +1317,11 @@ def test_builtin_license(self):
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
Expand All @@ -1328,10 +1333,10 @@ def test_builtin_license(self):
# 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}
Expand All @@ -1344,18 +1349,18 @@ def test_builtin_license(self):
'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')
result = LicenseSerializer(context={'request': lang_request}).to_representation(
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',)}
Expand Down
1 change: 1 addition & 0 deletions src/olympia/amo/management/commands/data_seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def handle(self, *args, **options):
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',
Expand Down
2 changes: 2 additions & 0 deletions src/olympia/amo/tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ class Commands:
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',
Expand Down Expand Up @@ -805,6 +806,7 @@ def test_default(self):
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),
Expand Down
15 changes: 15 additions & 0 deletions src/olympia/applications/management/commands/import_licenses.py
Original file line number Diff line number Diff line change
@@ -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
111 changes: 70 additions & 41 deletions src/olympia/constants/licenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_GPL3(_LicenseBase):
name = _('GNU General Public License v3.0')
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
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-3.0-or-later'
slug = 'GPL-2.0-only'


class LICENSE_LGPL2(_LicenseBase):
name = _('GNU Lesser General Public License v2.1')
url = 'https://www.gnu.org/licenses/lgpl-2.1.html'
class LICENSE_GPL3(_LicenseBase):
name = _('GNU General Public License v3.0 only')
url = 'https://spdx.org/licenses/GPL-3.0-only.html'
builtin = 4
slug = 'LGPL-2.1-or-later'
slug = 'GPL-3.0-only'


class LICENSE_LGPL3(_LicenseBase):
name = _('GNU Lesser General Public License v3.0')
url = 'https://www.gnu.org/licenses/lgpl-3.0.html'
class LICENSE_LGPL2(_LicenseBase):
name = _('GNU Lesser General Public License v2.1 only')
url = 'https://spdx.org/licenses/LGPL-2.1-only.html'
builtin = 5
slug = 'LGPL-3.0-or-later'
slug = 'LGPL-2.1-only'


class LICENSE_MIT(_LicenseBase):
name = _('The MIT License')
url = 'https://www.opensource.org/license/mit'
class LICENSE_LGPL3(_LicenseBase):
name = _('GNU Lesser General Public License v3.0 only')
url = 'https://spdx.org/licenses/LGPL-3.0-only.html'
builtin = 6
slug = 'MIT'
slug = 'LGPL-3.0-only'


class LICENSE_BSD(_LicenseBase):
name = _('The 2-Clause BSD License')
url = 'https://www.opensource.org/license/bsd-2-clause'
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 = 'BSD-2-Clause'
slug = 'AGPL-3.0-only'


# builtin 8, 9 aren't used in any current versions, and aren't available for selection.
class LICENSE_MIT(_LicenseBase):
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 = _('BSD 2-Clause "Simplified" License')
url = 'https://spdx.org/licenses/BSD-2-Clause.html'
builtin = 10
slug = 'BSD-2-Clause'


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

Expand All @@ -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'

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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'
Expand Down Expand Up @@ -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,
Expand All @@ -231,6 +256,10 @@ class LICENSE_CC_BY_SA40(_LicenseBase):
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 = {
Expand Down
2 changes: 1 addition & 1 deletion src/olympia/devhub/tests/test_views_ownership.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def test_no_license_required_for_unlisted(self):
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
Expand Down
6 changes: 4 additions & 2 deletions src/olympia/devhub/tests/test_views_submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1836,7 +1836,7 @@ def get_dict(self, minimal=True, **kw):
}
)
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)
Expand Down Expand Up @@ -1922,7 +1922,9 @@ def test_creative_commons_licenses(self):
)

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
Expand Down
Loading

0 comments on commit fe5a4e8

Please sign in to comment.