diff --git a/rhodecode/bin/rhodecode_config.py b/rhodecode/bin/rhodecode_config.py --- a/rhodecode/bin/rhodecode_config.py +++ b/rhodecode/bin/rhodecode_config.py @@ -93,8 +93,6 @@ def _run(argv): print parser.print_help() sys.exit(0) # defaults that can be overwritten by arguments - from rhodecode.model.license import LicenseModel - license_token = LicenseModel.generate_license_token() tmpl_stored_args = { 'http_server': 'waitress', 'lang': 'en', @@ -102,7 +100,6 @@ def _run(argv): 'host': '127.0.0.1', 'port': 5000, 'error_aggregation_service': None, - 'license_token': license_token } if other: # parse arguments, we assume only first is correct diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -346,11 +346,6 @@ def make_map(config): m.connect("admin_settings_system_update", "/settings/system/updates", action="settings_system_update", conditions=dict(method=["GET"])) - m.connect("admin_settings_license", "/settings/license", - action="settings_license", conditions=dict(method=["POST"])) - m.connect("admin_settings_license", "/settings/license", - action="settings_license", conditions=dict(method=["GET"])) - #ADMIN MY ACCOUNT with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/my_account') as m: diff --git a/rhodecode/controllers/admin/settings.py b/rhodecode/controllers/admin/settings.py --- a/rhodecode/controllers/admin/settings.py +++ b/rhodecode/controllers/admin/settings.py @@ -42,7 +42,6 @@ from rhodecode.lib.utils import repo2db_ from rhodecode.model.db import RhodeCodeUi, Repository, RhodeCodeSetting from rhodecode.model.forms import ApplicationSettingsForm, \ ApplicationUiSettingsForm, ApplicationVisualisationForm -from rhodecode.model.license import LicenseModel from rhodecode.model.scm import ScmModel from rhodecode.model.notification import EmailNotificationModel from rhodecode.model.meta import Session @@ -517,63 +516,3 @@ class SettingsController(BaseController) c.important_notices = latest['general'] return render('admin/settings/settings_system_update.html'), - - @HasPermissionAllDecorator('hg.admin') - def settings_license(self): - """GET /admin/settings/hooks: All items in the collection""" - # url('admin_settings_license') - c.active = 'license' - if request.POST: - form_result = request.POST - try: - sett1 = RhodeCodeSetting.create_or_update('license_key', - form_result['rhodecode_license_key'], - 'unicode') - Session().add(sett1) - Session().commit() - set_rhodecode_config(config) - h.flash(_('Updated license information'), - category='success') - - except Exception: - log.error(traceback.format_exc()) - h.flash(_('Error occurred during updating license info'), - category='error') - - return redirect(url('admin_settings_license')) - - defaults = RhodeCodeSetting.get_app_settings() - defaults.update(self._get_hg_ui_settings()) - - import rhodecode - c.rhodecode_ini = rhodecode.CONFIG - c.license_token = c.rhodecode_ini.get('license_token') - c.generated_license_token = LicenseModel.generate_license_token() - c.license_info = {} - c.license_loaded = False - # try to read info about license - try: - license_key = defaults.get('rhodecode_license_key') - if c.license_token and license_key: - c.license_info = json.loads( - LicenseModel(key=c.license_token).decrypt(license_key)) - expires = h.fmt_date(h.time_to_datetime(c.license_info['valid_till'])) - now = time.time() - if 0 < (c.license_info['valid_till'] - now) < 60*60*24*7: - h.flash(_('Your license will expire on %s, please contact ' - 'support to extend your license.' % expires), category='warning') - if c.license_info['valid_till'] - now < 0: - h.flash(_('Your license has expired on %s, please contact ' - 'support to extend your license.' % expires), category='error') - c.license_loaded = True - except Exception, e: - log.error(traceback.format_exc()) - h.flash(_('Unexpected error while reading license key. Please ' - 'make sure your license token and key are correct'), - category='error') - - return htmlfill.render( - render('admin/settings/settings.html'), - defaults=defaults, - encoding="UTF-8", - force_defaults=False) diff --git a/rhodecode/lib/hooks.py b/rhodecode/lib/hooks.py --- a/rhodecode/lib/hooks.py +++ b/rhodecode/lib/hooks.py @@ -258,30 +258,6 @@ def check_allowed_create_user(user_dict, if not allowed: raise UserCreationError(reason) - # license limit hook - import rhodecode - from rhodecode.model.license import LicenseModel - license_token = rhodecode.CONFIG.get('license_token') - license_key = LicenseModel.get_license_key() - license_info = LicenseModel.get_license_info( - license_token=license_token, enc_license_key=license_key, - fill_defaults=True) - expiration_check = False - if expiration_check: - now = time.time() - #check expiration - if now > license_info['valid_till']: - reason = ('Your license has expired, ' - 'please contact support to extend your license.') - raise UserCreationError(reason) - # user count check - cur_user_count = User.query().count() - if cur_user_count > int(license_info['users']) > 0: - reason = ('You have reached the maximum number of users (%s), ' - 'please contact support to extend your license.' - % license_info['users']) - raise UserCreationError(reason) - def log_create_user(user_dict, created_by, **kwargs): """ diff --git a/rhodecode/model/license.py b/rhodecode/model/license.py deleted file mode 100644 --- a/rhodecode/model/license.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -""" -rhodecode.model.license -~~~~~~~~~~~~~~~~~~~~~~~ - -Model for licenses - - -:created_on: Aug 1, 2013 -:author: marcink -:copyright: (c) 2013 RhodeCode GmbH. -:license: GPLv3, see LICENSE for more details. -""" - -import uuid -import base64 -import time -import logging -import traceback - -from Crypto import Random -from Crypto.Cipher import AES - -import rhodecode -from rhodecode.lib.compat import json -from rhodecode.model import BaseModel -from rhodecode.model.db import RhodeCodeSetting - -log = logging.getLogger(__name__) - -BLOCK_SIZE = 32 - - -def pad(s): - return (s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * - chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)) - - -def unpad(s): - return s[0:-ord(s[-1])] - - -class LicenseModel(BaseModel): - - cls = RhodeCodeSetting - - def __init__(self, sa=None, key=None): - super(LicenseModel, self).__init__(sa=sa) - if not key: - key = rhodecode.CONFIG.get('license_token') - - if not key: - raise TypeError('Missing encryption key: %s' % key) - if not isinstance(key, basestring): - raise TypeError('Encryption key is bad type, got %s ' - 'expected basestring' % type(key)) - #strip dashes - self.key = key.replace('-', '') - - @classmethod - def generate_license_token(cls): - tok_len = 4 - hex_token = uuid.uuid1().hex - num_pools = [hex_token[start:start+tok_len] - for start in range(0, len(hex_token), tok_len)] - return u'-'.join(num_pools[:4]) - - @classmethod - def get_default_license(cls): - - key = 'abra-cada-bra1-rce3' - enc_license_key = (''' - 0HBgVSMJgapshyHBZGiSj/pqSLkO8BmkbSnFDw8j+e854FkSJuVyUhIyUSFgs5mJ+P - KGknkw/LOf0pKLRZ7EZiFW+lkrv99UaS395FCp4J+ymdg7YdIdYtc0FZ8TcZjXrV3y - ORR3Klsjf7PUV6XVYSU6CAMx5SyK78n3JwYLclCnog1lD4kwHEFJH+OD5jFG3OT9eN - Kd0c1rVIJbbkPfppVIa4twr52bXWjueOpamdFI7DOJtlse9XyY1axgGNVQDtgRlWi5 - YmtP8OfT+Rq9SaCMQzPq3R42/YWHHrG1fhEMO7DAuruyLASoXROAo+hZmDoWYiqOP2 - vtJk/vc6WTB0Ro5zBWznFvkvTPzpFNf+A4FlQzQrVLjVOdIKncyJLx7QFHYFWT9ewD - Abr3XpaN5brqe97hDslN/8uKZabUydYI4dKDYkuc5+WAOfPGuqM/CwIPjZQ6K8ivJK - yX3CHBThwQuJtQY85GHPte0fT0bHoQyLIBwwYa76/pdm4eTaUrMZbj2HipDGTRO6BU - DaDIdw5YiczQ+Jec5phmqwbJ5Z/uXzdV6dhFLDTaiQ+PSkRLg9F1/cPZZxYOo8Jatn - 6pSQvmzi4ALTsaPIGGyu5aazPRB0Wz7g2tyPfUcAP5rzS0aWIdoszsAXizBiJdKgr4 - X2SlOqJ3MYfen4rvLbIQwV2IiRJdtv1QoFGAyyGfDtGzYruZbpfQcouhwRJbaESTwB - 0WXMa73Q2jw59GiTB5C4U=''') - return json.loads(LicenseModel(key=key).decrypt(enc_license_key)) - - @classmethod - def get_license_info(cls, license_token, enc_license_key, safe=True, - fill_defaults=False): - license_info = {} - if fill_defaults: - license_info = cls.get_default_license() - try: - if license_token and enc_license_key: - license_info = json.loads( - LicenseModel(key=license_token).decrypt(enc_license_key)) - except Exception, e: - log.error(traceback.format_exc()) - if not safe: - raise - return license_info - - @classmethod - def get_license_key(cls): - defaults = RhodeCodeSetting.get_app_settings() - return defaults.get('rhodecode_license_key') - - def encrypt(self, text, key=None): - if not isinstance(text, basestring): - raise TypeError('Encrypt can only work on unicode or ' - 'string, got %s' % type(text)) - if not key: - key = self.key - padded_text = pad(text) - IV = Random.new().read(AES.block_size) - cipher = AES.new(key, AES.MODE_CBC, IV) - return base64.b64encode(IV + cipher.encrypt(padded_text)) - - def decrypt(self, enc_text, key=None): - if not isinstance(enc_text, (unicode, str)): - raise TypeError('Encrypt can only work on unicode or ' - 'string, got %s' % type(enc_text)) - if not key: - key = self.key - enc = base64.b64decode(enc_text) - iv = enc[:16] # iv is stored - cipher = AES.new(key, AES.MODE_CBC, iv) - return unpad(cipher.decrypt(enc[16:])) - - def generate_signature(self, license_key, sig_key): - copy = license_key.copy() - del copy['signature'] - return self.encrypt(json.dumps(copy), key=sig_key) - - def verify(self, enc_text, sig_key): - if not isinstance(enc_text, basestring): - raise TypeError('Encrypt can only work on unicode or ' - 'string, got %s' % type(enc_text)) - - decrypted = json.loads(self.decrypt(enc_text)) - try: - signature = json.loads(self.decrypt(decrypted['signature'], sig_key)) - except Exception: - signature = '-- decryption error --' - - del decrypted['signature'] - #TODO: write better diff display - if decrypted != signature: - raise TypeError('Signature mismatch got %s[%s] vs %s[%s]' - % (decrypted, type(decrypted), signature, type(signature))) - return signature diff --git a/rhodecode/templates/admin/settings/settings.html b/rhodecode/templates/admin/settings/settings.html --- a/rhodecode/templates/admin/settings/settings.html +++ b/rhodecode/templates/admin/settings/settings.html @@ -45,8 +45,6 @@
  • ${_('Hooks')}
  • ${_('Full text search')}
  • ${_('System Info')}
  • -
  • ${_('License')}
  • - diff --git a/rhodecode/templates/admin/settings/settings_license.html b/rhodecode/templates/admin/settings/settings_license.html deleted file mode 100644 --- a/rhodecode/templates/admin/settings/settings_license.html +++ /dev/null @@ -1,59 +0,0 @@ -%if not c.license_loaded: -${_("Currently you're using a free license, which is limited to 20 users.")} -

    -%endif - -
    -<% - elems = [ - (_('RhodeCode version'), c.rhodecode_version, ''), - (_('License token'), h.literal('
    %s
    ' % c.rhodecode_ini.get('license_token', _('No license token'))), ''), - ] - if c.license_info: - elems.append((_('License issued to'), '%s %s (%s)' % (c.license_info.get('first_name'),c.license_info.get('last_name'),c.license_info.get('company')), '')) - elems.append((_('License issued on'), h.fmt_date(h.time_to_datetime(c.license_info.get('issue_date'))), '')) - elems.append((_('License users limit'), c.license_info.get('users') if c.license_info.get('users') != -1 else _('unlimited'), '')) - elems.append((_('License expires on'), h.fmt_date(h.time_to_datetime(c.license_info.get('valid_till'))), '')) -%> -%for dt, dd, tt in elems: -
    ${dt}:
    -
    ${dd}
    -%endfor -
    - - -%if c.license_token: -${h.form(url('admin_settings_license'), method='post')} -
    - -
    - -
    -
    - -
    -
    - ${h.textarea('rhodecode_license_key', style="height:165px")} - ${_('Paste your RhodeCode license key into that textarea.')} -
    -
    - -
    - ${h.submit('save',_('Save settings'),class_="btn")} - ${h.reset('reset',_('Reset'),class_="btn")} -
    -
    -
    -${h.end_form()} - - -%else: -
    -${_('Please enter following lines (if yet not present) into [app:main] section of your .ini file. The token below is autogenerated.')} -
    -
    -<%text>## license token
    -license_token = ${c.generated_license_token}
    -
    -
    -%endif diff --git a/rhodecode/tests/models/test_license.py b/rhodecode/tests/models/test_license.py deleted file mode 100644 --- a/rhodecode/tests/models/test_license.py +++ /dev/null @@ -1,68 +0,0 @@ -from __future__ import with_statement - -from rhodecode.tests import * -from rhodecode.tests.fixture import Fixture -from rhodecode.lib.compat import json -from rhodecode.model.license import LicenseModel - -fixture = Fixture() - -TEST_KEY = '' - - -class LicenseTest(BaseTestCase): - - def setUp(self): - global TEST_KEY - token = LicenseModel.generate_license_token() - TEST_KEY = token - - def test_encryption_decryption(self): - test_license = { - 'foo': 'baar', - 'signature': 'test' - } - enc = LicenseModel(key=TEST_KEY).encrypt(json.dumps(test_license)) - dec = json.loads(LicenseModel(key=TEST_KEY).decrypt(enc)) - self.assertEqual(test_license, dec) - - def test_signature(self): - enc_with_key = '1234567890123456' - test_license = { - 'foo': 'baar', - 'signature': None - } - test_license['signature'] = LicenseModel(key=TEST_KEY)\ - .generate_signature(test_license, enc_with_key) - - enc = LicenseModel(key=TEST_KEY).encrypt(json.dumps(test_license)) - signature = LicenseModel(key=TEST_KEY).verify(enc, enc_with_key) - - del test_license['signature'] - self.assertEqual(test_license, signature) - - def test_signature_mismatch(self): - enc_with_key = '1234567890123456' - test_license = { - 'foo': 'baar', - 'signature': 'cnashs62tdsbcsaaisuda6215sagc' - } - - enc = LicenseModel(key=TEST_KEY).encrypt(json.dumps(test_license)) - - self.assertRaises(TypeError, - lambda: LicenseModel(key=TEST_KEY).verify(enc, enc_with_key)) - - def test_generate_license_token(self): - token = LicenseModel.generate_license_token() - self.assertEqual(4, len(token.split('-'))) - - def test_get_license_info(self): - info = LicenseModel.get_license_info('', '') - self.assertEqual(info, {}) - - def test_get_license_info_default(self): - info = LicenseModel.get_license_info('', '', fill_defaults=True) - self.assertEqual(info['users'], 20) - self.assertEqual(info['valid_till'], 1421884937.512214) - self.assertEqual(info['email'], 'support@rhodecode.com')