<commit_before>'''
Copyright 2013 <NAME> <<EMAIL>>

This file is part of ddserver.

ddserver is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

ddserver 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with ddserver. If not, see <http://www.gnu.org/licenses/>.
'''

import bottle

from ddserver.web import route

from ddserver.utils.deps import extend, require

from ddserver.interface.user import authorized

from ddserver.interface import validation
from ddserver.interface.validation import validate

from passlib.apps import custom_app_context as pwd



@extend('ddserver.config:ConfigDeclaration')
def config_auth(config_decl):
  with config_decl.declare('dns') as s:
    s('max_hosts',
       conv = int,
       default = 5)



@route('/user/hosts/list', method = 'GET')
@authorized()
@require(db = 'ddserver.db:Database',
         templates = 'ddserver.interface.template:TemplateManager')
def get_hosts_display(user,
                      db,
                      templates):
  ''' Display the users hostnames and a form for adding new ones. '''

  with db.cursor() as cur:
    # Get hosts of the user
    cur.execute('''
        SELECT
          `host`.`id` AS `id`,
          `host`.`hostname` AS `hostname`,
          `suffix`.`name` AS `suffix`,
          `host`.`address` AS `address`,
          `host`.`updated` AS `updated`
        FROM `hosts` AS `host`
        LEFT JOIN `suffixes` AS `suffix`
          ON ( `suffix`.`id` = `host`.`suffix_id` )
        WHERE `user_id` = %(user_id)s
    ''', {'user_id': user.id})
    hosts = cur.fetchall()

  return templates['hosts.html'](hosts = hosts)



@route('/user/hosts/add', method = 'GET')
@authorized()
@require(db = 'ddserver.db:Database',
         config = 'ddserver.config:Config',
         templates = 'ddserver.interface.template:TemplateManager')
def get_hosts_add(user,
                  db,
                  config,
                  templates):
  ''' form for adding new hostnames '''

  with db.cursor() as cur:
    # Get all available suffixes
    cur.execute('''
        SELECT *
        FROM `suffixes`
    ''')
    suffixes = cur.fetchall()

    # Get number of hosts of the user
    cur.execute('''
        SELECT
          COUNT(`host`.`id`) AS `count`
        FROM `hosts` AS `host`
        WHERE `user_id` = %(user_id)s
    ''', {'user_id': user.id})
    hosts = cur.fetchone()

  return templates['addhost.html'](hosts = hosts,
                                   suffixes = suffixes,
                                   current_ip = bottle.request.remote_addr)



@route('/user/hosts/add', method = 'POST')
@authorized()
@validate('/user/hosts/add',
          hostname = validation.UniqueHostname(),
          suffix = validation.Int(not_empty = True),
          address = validation.IPAddress(),
          password = validation.SecurePassword(min = 8),
          password_confirm = validation.String(),
          chained_validators = [validation.FieldsMatch('password', 'password_confirm')])
@require(db = 'ddserver.db:Database',
         config = 'ddserver.config:Config',
         messages = 'ddserver.interface.message:MessageManager')
def post_hosts_add(user,
                   data,
                   db,
                   config,
                   messages):
  ''' Add a new hostname. '''

  # We do net check passed suffix, as mysql will tell us later on

  encrypted_password = pwd.encrypt(data.password)

  with db.cursor() as cur:
    cur.execute('''
      SELECT *
      FROM `hosts`
      WHERE `user_id` = %(user_id)s
    ''', {'user_id': user.id})

    if cur.rowcount >= config.dns.max_hosts:
      messages.error('Maximum number of hosts reached')
      bottle.redirect('/user/hosts')

    cur.execute('''
      INSERT
      INTO `hosts`
      SET `hostname` = %(hostname)s,
          `address` = %(address)s,
          `password` = %(<PASSWORD>,
          `user_id` = %(user_id)s,
          `suffix_id` = %(suffix_id)s
    ''', {'hostname': data.hostname,
          'address': data.address,
          'password': <PASSWORD>,
          'user_id' : user.id,
          'suffix_id': data.suffix})

  messages.success('Ok, done.')

  bottle.redirect('/user/hosts/list')



@route('/user/hosts/delete', method = 'POST')
@authorized()
@validate('/user/hosts/list',
          host_id = validation.Int(not_empty = True))
@require(db = 'ddserver.db:Database',
         messages = 'ddserver.interface.message:MessageManager')
def post_hosts_delete(user,
                      data,
                      db,
                      messages):
  ''' Delete a hostname. '''

  # We do not check the host id for existence and belonging as we only delete
  # host of the user

  with db.cursor() as cur:
    cur.execute('''
        DELETE
        FROM hosts
        WHERE id = %(host_id)s
          AND user_id = %(user_id)s
    ''', {'host_id': data.host_id,
          'user_id': user.id})

  messages.success('Ok, done.')

  bottle.redirect('/user/hosts/list')
<commit_msg>allow infinite hostnames for admin users<commit_after>'''
Copyright 2013 <NAME> <<EMAIL>>

This file is part of ddserver.

ddserver is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

ddserver 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with ddserver. If not, see <http://www.gnu.org/licenses/>.
'''

import bottle

from ddserver.web import route

from ddserver.utils.deps import extend, require

from ddserver.interface.user import authorized

from ddserver.interface import validation
from ddserver.interface.validation import validate

from passlib.apps import custom_app_context as pwd



@extend('ddserver.config:ConfigDeclaration')
def config_auth(config_decl):
  with config_decl.declare('dns') as s:
    s('max_hosts',
       conv = int,
       default = 5)



@route('/user/hosts/list', method = 'GET')
@authorized()
@require(db = 'ddserver.db:Database',
         templates = 'ddserver.interface.template:TemplateManager')
def get_hosts_display(user,
                      db,
                      templates):
  ''' Display the users hostnames and a form for adding new ones. '''

  with db.cursor() as cur:
    # Get hosts of the user
    cur.execute('''
        SELECT
          `host`.`id` AS `id`,
          `host`.`hostname` AS `hostname`,
          `suffix`.`name` AS `suffix`,
          `host`.`address` AS `address`,
          `host`.`updated` AS `updated`
        FROM `hosts` AS `host`
        LEFT JOIN `suffixes` AS `suffix`
          ON ( `suffix`.`id` = `host`.`suffix_id` )
        WHERE `user_id` = %(user_id)s
    ''', {'user_id': user.id})
    hosts = cur.fetchall()

  return templates['hosts.html'](hosts = hosts)



@route('/user/hosts/add', method = 'GET')
@authorized()
@require(db = 'ddserver.db:Database',
         config = 'ddserver.config:Config',
         templates = 'ddserver.interface.template:TemplateManager')
def get_hosts_add(user,
                  db,
                  config,
                  templates):
  ''' form for adding new hostnames '''

  with db.cursor() as cur:
    # Get all available suffixes
    cur.execute('''
        SELECT *
        FROM `suffixes`
    ''')
    suffixes = cur.fetchall()

    # Get number of hosts of the user
    cur.execute('''
        SELECT
          COUNT(`host`.`id`) AS `count`
        FROM `hosts` AS `host`
        WHERE `user_id` = %(user_id)s
    ''', {'user_id': user.id})
    hosts = cur.fetchone()

  return templates['addhost.html'](hosts = hosts,
                                   suffixes = suffixes,
                                   current_ip = bottle.request.remote_addr)



@route('/user/hosts/add', method = 'POST')
@authorized()
@validate('/user/hosts/add',
          hostname = validation.UniqueHostname(),
          suffix = validation.Int(not_empty = True),
          address = validation.IPAddress(),
          password = validation.SecurePassword(min = 8),
          password_confirm = validation.String(),
          chained_validators = [validation.FieldsMatch('password', 'password_confirm')])
@require(db = 'ddserver.db:Database',
         config = 'ddserver.config:Config',
         messages = 'ddserver.interface.message:MessageManager')
def post_hosts_add(user,
                   data,
                   db,
                   config,
                   messages):
  ''' Add a new hostname. '''

  # We do net check passed suffix, as mysql will tell us later on

  encrypted_password = <PASSWORD>(data.password)

  with db.cursor() as cur:
    cur.execute('''
      SELECT *
      FROM `hosts`
      WHERE `user_id` = %(user_id)s
    ''', {'user_id': user.id})

    if (not user.admin) or (cur.rowcount >= config.dns.max_hosts):
      messages.error('Maximum number of hosts reached')
      bottle.redirect('/user/hosts')

    cur.execute('''
      INSERT
      INTO `hosts`
      SET `hostname` = %(hostname)s,
          `address` = %(address)s,
          `password` = %(<PASSWORD>,
          `user_id` = %(user_id)s,
          `suffix_id` = %(suffix_id)s
    ''', {'hostname': data.hostname,
          'address': data.address,
          'password': <PASSWORD>,
          'user_id' : user.id,
          'suffix_id': data.suffix})

  messages.success('Ok, done.')

  bottle.redirect('/user/hosts/list')



@route('/user/hosts/delete', method = 'POST')
@authorized()
@validate('/user/hosts/list',
          host_id = validation.Int(not_empty = True))
@require(db = 'ddserver.db:Database',
         messages = 'ddserver.interface.message:MessageManager')
def post_hosts_delete(user,
                      data,
                      db,
                      messages):
  ''' Delete a hostname. '''

  # We do not check the host id for existence and belonging as we only delete
  # host of the user

  with db.cursor() as cur:
    cur.execute('''
        DELETE
        FROM hosts
        WHERE id = %(host_id)s
          AND user_id = %(user_id)s
    ''', {'host_id': data.host_id,
          'user_id': user.id})

  messages.success('Ok, done.')

  bottle.redirect('/user/hosts/list')

{'fraction_non_alphanumeric': 0.12651933701657458, 'fraction_numerical': 0.001289134438305709, 'mean_word_length': 2.468859789204727, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1870272', 'n_tokens_mistral': 3299, 'n_tokens_neox': 3156, 'n_words': 902}