API & Client - refactor registration activation - #15
This commit is contained in:
		@@ -144,8 +144,7 @@
 | 
			
		||||
    <span class="nt">"is_registration_enabled"</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"max_single_file_size"</span><span class="p">:</span> <span class="mi">1048576</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"max_zip_file_size"</span><span class="p">:</span> <span class="mi">10485760</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"max_users"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"registration"</span><span class="p">:</span> <span class="kc">false</span>
 | 
			
		||||
    <span class="nt">"max_users"</span><span class="p">:</span> <span class="mi">0</span>
 | 
			
		||||
  <span class="p">},</span>
 | 
			
		||||
  <span class="nt">"status"</span><span class="p">:</span> <span class="s2">"success"</span>
 | 
			
		||||
<span class="p">}</span>
 | 
			
		||||
@@ -181,8 +180,7 @@
 | 
			
		||||
    <span class="nt">"is_registration_enabled"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"max_single_file_size"</span><span class="p">:</span> <span class="mi">1048576</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"max_zip_file_size"</span><span class="p">:</span> <span class="mi">10485760</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"max_users"</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
 | 
			
		||||
    <span class="nt">"registration"</span><span class="p">:</span> <span class="kc">true</span>
 | 
			
		||||
    <span class="nt">"max_users"</span><span class="p">:</span> <span class="mi">10</span>
 | 
			
		||||
  <span class="p">},</span>
 | 
			
		||||
  <span class="nt">"status"</span><span class="p">:</span> <span class="s2">"success"</span>
 | 
			
		||||
<span class="p">}</span>
 | 
			
		||||
@@ -197,10 +195,10 @@
 | 
			
		||||
<dt class="field-even">Request JSON Object</dt>
 | 
			
		||||
<dd class="field-even"><ul class="simple">
 | 
			
		||||
<li><p><strong>gpx_limit_import</strong> (<em>integrer</em>) – max number of files in zip archive</p></li>
 | 
			
		||||
<li><p><strong>is_registration_enabled</strong> (<em>boolean</em>) – is registration enabled ?</p></li>
 | 
			
		||||
<li><p><strong>max_single_file_size</strong> (<em>integrer</em>) – max size of a single file</p></li>
 | 
			
		||||
<li><p><strong>max_zip_file_size</strong> (<em>integrer</em>) – max size of a zip archive</p></li>
 | 
			
		||||
<li><p><strong>max_users</strong> (<em>integrer</em>) – max users allowed to register on instance</p></li>
 | 
			
		||||
<li><p><strong>registration</strong> (<em>boolean</em>) – is registration enabled ?</p></li>
 | 
			
		||||
</ul>
 | 
			
		||||
</dd>
 | 
			
		||||
<dt class="field-odd">Request Headers</dt>
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,7 @@ def get_application_config():
 | 
			
		||||
          "is_registration_enabled": false,
 | 
			
		||||
          "max_single_file_size": 1048576,
 | 
			
		||||
          "max_zip_file_size": 10485760,
 | 
			
		||||
          "max_users": 0,
 | 
			
		||||
          "registration": false
 | 
			
		||||
          "max_users": 0
 | 
			
		||||
        },
 | 
			
		||||
        "status": "success"
 | 
			
		||||
      }
 | 
			
		||||
@@ -85,8 +84,7 @@ def update_application_config(auth_user_id):
 | 
			
		||||
          "is_registration_enabled": true,
 | 
			
		||||
          "max_single_file_size": 1048576,
 | 
			
		||||
          "max_zip_file_size": 10485760,
 | 
			
		||||
          "max_users": 10,
 | 
			
		||||
          "registration": true
 | 
			
		||||
          "max_users": 10
 | 
			
		||||
        },
 | 
			
		||||
        "status": "success"
 | 
			
		||||
      }
 | 
			
		||||
@@ -94,10 +92,10 @@ def update_application_config(auth_user_id):
 | 
			
		||||
    :param integer auth_user_id: authenticate user id (from JSON Web Token)
 | 
			
		||||
 | 
			
		||||
    :<json integrer gpx_limit_import: max number of files in zip archive
 | 
			
		||||
    :<json boolean is_registration_enabled: is registration enabled ?
 | 
			
		||||
    :<json integrer max_single_file_size: max size of a single file
 | 
			
		||||
    :<json integrer max_zip_file_size: max size of a zip archive
 | 
			
		||||
    :<json integrer max_users: max users allowed to register on instance
 | 
			
		||||
    :<json boolean registration: is registration enabled ?
 | 
			
		||||
 | 
			
		||||
    :reqheader Authorization: OAuth 2.0 Bearer Token
 | 
			
		||||
 | 
			
		||||
@@ -127,8 +125,6 @@ def update_application_config(auth_user_id):
 | 
			
		||||
            config.max_zip_file_size = config_data.get('max_zip_file_size')
 | 
			
		||||
        if 'max_users' in config_data:
 | 
			
		||||
            config.max_users = config_data.get('max_users')
 | 
			
		||||
        if 'registration' in config_data:
 | 
			
		||||
            config.registration = config_data.get('registration')
 | 
			
		||||
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        update_app_config_from_database(current_app, config)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ from ..users.models import User
 | 
			
		||||
class AppConfig(db.Model):
 | 
			
		||||
    __tablename__ = 'app_config'
 | 
			
		||||
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
 | 
			
		||||
    registration = db.Column(db.Boolean, default=False, nullable=False)
 | 
			
		||||
    max_users = db.Column(db.Integer, default=0, nullable=False)
 | 
			
		||||
    gpx_limit_import = db.Column(db.Integer, default=10, nullable=False)
 | 
			
		||||
    max_single_file_size = db.Column(
 | 
			
		||||
@@ -17,7 +16,7 @@ class AppConfig(db.Model):
 | 
			
		||||
    @property
 | 
			
		||||
    def is_registration_enabled(self):
 | 
			
		||||
        nb_users = User.query.count()
 | 
			
		||||
        return self.registration and nb_users < self.max_users
 | 
			
		||||
        return self.max_users == 0 or nb_users < self.max_users
 | 
			
		||||
 | 
			
		||||
    def serialize(self):
 | 
			
		||||
        return {
 | 
			
		||||
@@ -26,5 +25,4 @@ class AppConfig(db.Model):
 | 
			
		||||
            "max_single_file_size": self.max_single_file_size,
 | 
			
		||||
            "max_zip_file_size": self.max_zip_file_size,
 | 
			
		||||
            "max_users": self.max_users,
 | 
			
		||||
            "registration": self.registration,
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from fittrackee_api import db
 | 
			
		||||
from fittrackee_api.users.models import User
 | 
			
		||||
 | 
			
		||||
from .models import AppConfig
 | 
			
		||||
 | 
			
		||||
@@ -15,14 +16,14 @@ def init_config():
 | 
			
		||||
    (for FitTrackee versions prior to v0.3.0)
 | 
			
		||||
    """
 | 
			
		||||
    existing_config = AppConfig.query.one_or_none()
 | 
			
		||||
    nb_users = User.query.count()
 | 
			
		||||
    if not existing_config:
 | 
			
		||||
        config = AppConfig()
 | 
			
		||||
        config.registration = (
 | 
			
		||||
            False
 | 
			
		||||
        config.max_users = (
 | 
			
		||||
            nb_users
 | 
			
		||||
            if os.getenv('REACT_APP_ALLOW_REGISTRATION') == "false"
 | 
			
		||||
            else True
 | 
			
		||||
            else 0
 | 
			
		||||
        )
 | 
			
		||||
        config.max_users = 0
 | 
			
		||||
        config.max_single_file_size = os.environ.get(
 | 
			
		||||
            'REACT_APP_MAX_SINGLE_FILE_SIZE', MAX_FILE_SIZE
 | 
			
		||||
        )
 | 
			
		||||
@@ -40,7 +41,6 @@ def update_app_config_from_database(current_app, db_config):
 | 
			
		||||
    current_app.config['max_single_file_size'] = db_config.max_single_file_size
 | 
			
		||||
    current_app.config['MAX_CONTENT_LENGTH'] = db_config.max_zip_file_size
 | 
			
		||||
    current_app.config['max_users'] = db_config.max_users
 | 
			
		||||
    current_app.config['registration'] = db_config.registration
 | 
			
		||||
    current_app.config[
 | 
			
		||||
        'is_registration_enabled'
 | 
			
		||||
    ] = db_config.is_registration_enabled
 | 
			
		||||
 
 | 
			
		||||
@@ -12,44 +12,25 @@ os.environ["FLASK_ENV"] = 'testing'
 | 
			
		||||
os.environ["APP_SETTINGS"] = 'fittrackee_api.config.TestingConfig'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def app_config_with_registration():
 | 
			
		||||
    config = AppConfig()
 | 
			
		||||
    config.gpx_limit_import = 10
 | 
			
		||||
    config.max_single_file_size = 1 * 1024 * 1024
 | 
			
		||||
    config.max_zip_file_size = 1 * 1024 * 1024 * 10
 | 
			
		||||
    config.max_users = 10
 | 
			
		||||
    config.registration = True
 | 
			
		||||
    db.session.add(config)
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    return config
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def app_config_registration_disabled():
 | 
			
		||||
    config = AppConfig()
 | 
			
		||||
    config.gpx_limit_import = 20
 | 
			
		||||
    config.max_single_file_size = 10485
 | 
			
		||||
    config.max_zip_file_size = 104850
 | 
			
		||||
    config.max_users = 0
 | 
			
		||||
    config.registration = False
 | 
			
		||||
    db.session.add(config)
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    return config
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_app_config(app_type):
 | 
			
		||||
    if app_type == 'with_registration':
 | 
			
		||||
        return app_config_with_registration()
 | 
			
		||||
    elif app_type == 'no_registration':
 | 
			
		||||
        return app_config_registration_disabled()
 | 
			
		||||
def get_app_config(with_config=False):
 | 
			
		||||
    if with_config:
 | 
			
		||||
        config = AppConfig()
 | 
			
		||||
        config.gpx_limit_import = 10
 | 
			
		||||
        config.max_single_file_size = 1 * 1024 * 1024
 | 
			
		||||
        config.max_zip_file_size = 1 * 1024 * 1024 * 10
 | 
			
		||||
        config.max_users = 100
 | 
			
		||||
        db.session.add(config)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        return config
 | 
			
		||||
    else:
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_app(app_type=None):
 | 
			
		||||
def get_app(with_config=False):
 | 
			
		||||
    app = create_app()
 | 
			
		||||
    with app.app_context():
 | 
			
		||||
        db.create_all()
 | 
			
		||||
        app_db_config = get_app_config(app_type)
 | 
			
		||||
        app_db_config = get_app_config(with_config)
 | 
			
		||||
        if app_db_config:
 | 
			
		||||
            update_app_config_from_database(app, app_db_config)
 | 
			
		||||
        yield app
 | 
			
		||||
@@ -64,17 +45,12 @@ def get_app(app_type=None):
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def app():
 | 
			
		||||
    yield from get_app('with_registration')
 | 
			
		||||
    yield from get_app(with_config=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def app_no_config():
 | 
			
		||||
    yield from get_app()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def app_no_registration():
 | 
			
		||||
    yield from get_app('no_registration')
 | 
			
		||||
    yield from get_app(with_config=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture()
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,7 @@ def test_get_config(app, user_1):
 | 
			
		||||
    assert data['data']['is_registration_enabled'] is True
 | 
			
		||||
    assert data['data']['max_single_file_size'] == 1048576
 | 
			
		||||
    assert data['data']['max_zip_file_size'] == 10485760
 | 
			
		||||
    assert data['data']['max_users'] == 10
 | 
			
		||||
    assert data['data']['registration'] is True
 | 
			
		||||
    assert data['data']['max_users'] == 100
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_config_no_config(app_no_config, user_1_admin):
 | 
			
		||||
@@ -82,7 +81,7 @@ def test_update_config_as_admin(app, user_1_admin):
 | 
			
		||||
    response = client.patch(
 | 
			
		||||
        '/api/config',
 | 
			
		||||
        content_type='application/json',
 | 
			
		||||
        data=json.dumps(dict(registration=True, max_users=10)),
 | 
			
		||||
        data=json.dumps(dict(gpx_limit_import=100, max_users=10)),
 | 
			
		||||
        headers=dict(
 | 
			
		||||
            Authorization='Bearer '
 | 
			
		||||
            + json.loads(resp_login.data.decode())['auth_token']
 | 
			
		||||
@@ -92,12 +91,11 @@ def test_update_config_as_admin(app, user_1_admin):
 | 
			
		||||
 | 
			
		||||
    assert response.status_code == 200
 | 
			
		||||
    assert 'success' in data['status']
 | 
			
		||||
    assert data['data']['gpx_limit_import'] == 10
 | 
			
		||||
    assert data['data']['gpx_limit_import'] == 100
 | 
			
		||||
    assert data['data']['is_registration_enabled'] is True
 | 
			
		||||
    assert data['data']['max_single_file_size'] == 1048576
 | 
			
		||||
    assert data['data']['max_zip_file_size'] == 10485760
 | 
			
		||||
    assert data['data']['max_users'] == 10
 | 
			
		||||
    assert data['data']['registration'] is True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_update_full_config_as_admin(app, user_1_admin):
 | 
			
		||||
@@ -116,7 +114,6 @@ def test_update_full_config_as_admin(app, user_1_admin):
 | 
			
		||||
                max_single_file_size=10000,
 | 
			
		||||
                max_zip_file_size=25000,
 | 
			
		||||
                max_users=50,
 | 
			
		||||
                registration=True,
 | 
			
		||||
            )
 | 
			
		||||
        ),
 | 
			
		||||
        headers=dict(
 | 
			
		||||
@@ -133,7 +130,6 @@ def test_update_full_config_as_admin(app, user_1_admin):
 | 
			
		||||
    assert data['data']['max_single_file_size'] == 10000
 | 
			
		||||
    assert data['data']['max_zip_file_size'] == 25000
 | 
			
		||||
    assert data['data']['max_users'] == 50
 | 
			
		||||
    assert data['data']['registration'] is True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_update_config_not_admin(app, user_1):
 | 
			
		||||
@@ -146,7 +142,7 @@ def test_update_config_not_admin(app, user_1):
 | 
			
		||||
    response = client.patch(
 | 
			
		||||
        '/api/config',
 | 
			
		||||
        content_type='application/json',
 | 
			
		||||
        data=json.dumps(dict(registration=True, max_users=10)),
 | 
			
		||||
        data=json.dumps(dict(gpx_limit_import=100, max_users=10)),
 | 
			
		||||
        headers=dict(
 | 
			
		||||
            Authorization='Bearer '
 | 
			
		||||
            + json.loads(resp_login.data.decode())['auth_token']
 | 
			
		||||
@@ -193,7 +189,7 @@ def test_update_config_no_config(app_no_config, user_1_admin):
 | 
			
		||||
    response = client.patch(
 | 
			
		||||
        '/api/config',
 | 
			
		||||
        content_type='application/json',
 | 
			
		||||
        data=json.dumps(dict(registration=True, max_users=10)),
 | 
			
		||||
        data=json.dumps(dict(gpx_limit_import=100, max_users=10)),
 | 
			
		||||
        headers=dict(
 | 
			
		||||
            Authorization='Bearer '
 | 
			
		||||
            + json.loads(resp_login.data.decode())['auth_token']
 | 
			
		||||
 
 | 
			
		||||
@@ -10,5 +10,4 @@ def test_application_config(app):
 | 
			
		||||
    assert serialized_app_config['is_registration_enabled'] is True
 | 
			
		||||
    assert serialized_app_config['max_single_file_size'] == 1048576
 | 
			
		||||
    assert serialized_app_config['max_zip_file_size'] == 10485760
 | 
			
		||||
    assert serialized_app_config['max_users'] == 10
 | 
			
		||||
    assert serialized_app_config['registration'] is True
 | 
			
		||||
    assert serialized_app_config['max_users'] == 100
 | 
			
		||||
 
 | 
			
		||||
@@ -259,28 +259,6 @@ def test_user_registration_invalid_data(app):
 | 
			
		||||
    assert 'error' in data['status']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_user_registration_not_allowed(app_no_registration):
 | 
			
		||||
    client = app_no_registration.test_client()
 | 
			
		||||
    response = client.post(
 | 
			
		||||
        '/api/auth/register',
 | 
			
		||||
        data=json.dumps(
 | 
			
		||||
            dict(
 | 
			
		||||
                username='test',
 | 
			
		||||
                email='test@test.com',
 | 
			
		||||
                password='12345678',
 | 
			
		||||
                password_conf='12345678',
 | 
			
		||||
            )
 | 
			
		||||
        ),
 | 
			
		||||
        content_type='application/json',
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    assert response.content_type == 'application/json'
 | 
			
		||||
    assert response.status_code == 403
 | 
			
		||||
    data = json.loads(response.data.decode())
 | 
			
		||||
    assert data['status'] == 'error'
 | 
			
		||||
    assert data['message'] == 'Error. Registration is disabled.'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_user_registration_max_users_exceeded(
 | 
			
		||||
    app, user_1_admin, user_2, user_3
 | 
			
		||||
):
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ def upgrade():
 | 
			
		||||
    # ### commands auto generated by Alembic - please adjust! ###
 | 
			
		||||
    op.create_table('app_config',
 | 
			
		||||
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
 | 
			
		||||
    sa.Column('registration', sa.Boolean(), nullable=False),
 | 
			
		||||
    sa.Column('max_users', sa.Integer(), nullable=False),
 | 
			
		||||
    sa.Column('gpx_limit_import', sa.Integer(), nullable=False),
 | 
			
		||||
    sa.Column('max_single_file_size', sa.Integer(), nullable=False),
 | 
			
		||||
 
 | 
			
		||||
@@ -28,26 +28,17 @@ export default function Config({ appConfig, message, t, updateIsInEdition }) {
 | 
			
		||||
                      <tbody>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                          <th scope="row">
 | 
			
		||||
                            {t('administration:Enable registration')}:
 | 
			
		||||
                          </th>
 | 
			
		||||
                          <td>
 | 
			
		||||
                            {appConfig.registration
 | 
			
		||||
                              ? t('common:yes')
 | 
			
		||||
                              : t('common:no')}
 | 
			
		||||
                          </td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                          <th scope="row">
 | 
			
		||||
                            {t('administration:Max. number of active users')}:
 | 
			
		||||
                            {t(
 | 
			
		||||
                              // eslint-disable-next-line max-len
 | 
			
		||||
                              'administration:Max. number of active users (if 0, no limitation)'
 | 
			
		||||
                            )}
 | 
			
		||||
                            :
 | 
			
		||||
                          </th>
 | 
			
		||||
                          <td>{appConfig.max_users}</td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                          <th scope="row">
 | 
			
		||||
                            {t(
 | 
			
		||||
                              'administration:Max. size of ' + 'uploaded files'
 | 
			
		||||
                            )}
 | 
			
		||||
                            :
 | 
			
		||||
                            {t('administration:Max. size of uploaded files')}:
 | 
			
		||||
                          </th>
 | 
			
		||||
                          <td>{getFileSize(appConfig.max_single_file_size)}</td>
 | 
			
		||||
                        </tr>
 | 
			
		||||
 
 | 
			
		||||
@@ -73,28 +73,16 @@ class AdminApplication extends React.Component {
 | 
			
		||||
                        updateIsInEdition()
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      <div className="form-group row">
 | 
			
		||||
                        <label
 | 
			
		||||
                          className="col-sm-6 col-form-label"
 | 
			
		||||
                          htmlFor="registration"
 | 
			
		||||
                        >
 | 
			
		||||
                          {t('administration:Enable registration')}:
 | 
			
		||||
                        </label>
 | 
			
		||||
                        <input
 | 
			
		||||
                          className="col-sm-5"
 | 
			
		||||
                          id="registration"
 | 
			
		||||
                          name="registration"
 | 
			
		||||
                          type="checkbox"
 | 
			
		||||
                          checked={formData.registration}
 | 
			
		||||
                          onChange={e => this.handleFormChange(e)}
 | 
			
		||||
                        />
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div className="form-group row">
 | 
			
		||||
                        <label
 | 
			
		||||
                          className="col-sm-6 col-form-label"
 | 
			
		||||
                          htmlFor="max_users"
 | 
			
		||||
                        >
 | 
			
		||||
                          {t('administration:Max. number of active users')}:
 | 
			
		||||
                          {t(
 | 
			
		||||
                            // eslint-disable-next-line max-len
 | 
			
		||||
                            'administration:Max. number of active users (if 0, no limitation)'
 | 
			
		||||
                          )}
 | 
			
		||||
                          :
 | 
			
		||||
                        </label>
 | 
			
		||||
                        <input
 | 
			
		||||
                          className="col-sm-5"
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,11 @@
 | 
			
		||||
  "Back": "Back",
 | 
			
		||||
  "Disable": "Disable",
 | 
			
		||||
  "Enable": "Enable",
 | 
			
		||||
  "Enable registration": "Enable registration",
 | 
			
		||||
  "FitTrackee administration": "FitTrackee administration",
 | 
			
		||||
  "id": "id",
 | 
			
		||||
  "Image": "Image",
 | 
			
		||||
  "Label": "Label",
 | 
			
		||||
  "Max. number of active users": "Max. number of active users",
 | 
			
		||||
  "Max. number of active users (if 0, no limitation)": "Max. number of active users",
 | 
			
		||||
  "Max. files of zip archive": "Max. files of zip archive",
 | 
			
		||||
  "Max. size of uploaded files": "Max. size of uploaded files",
 | 
			
		||||
  "Max. size of uploaded files (in Mb)": "Max. size of uploaded files (in Mb)",
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,11 @@
 | 
			
		||||
  "Back": "Retour",
 | 
			
		||||
  "Disable": "désactiver",
 | 
			
		||||
  "Enable": "activer",
 | 
			
		||||
  "Enable registration": "Activer les inscriptions",
 | 
			
		||||
  "FitTrackee administration": "Administration de FitTrackee",
 | 
			
		||||
  "id": "id",
 | 
			
		||||
  "Image": "Image",
 | 
			
		||||
  "Label": "Label",
 | 
			
		||||
  "Max. number of active users": "Nombre maximum d'utilisateurs actifs",
 | 
			
		||||
  "Max. number of active users (if 0, no limitation)": "Nombre maximum d'utilisateurs actifs",
 | 
			
		||||
  "Max. files of zip archive": "Nombre max. de fichiers dans une archive zip",
 | 
			
		||||
  "Max. size of uploaded files": "Taille max. des fichiers",
 | 
			
		||||
  "Max. size of uploaded files (in Mb)": "Taille max. des fichiers (en Mo)",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user