def transfer(self, domain: Domain): if domain.epp_code is None: raise RegistrarConnectorException('EPP Code is missing') contact = domain.contact or domain.service.client owner_handle = self.find_or_create_customer(client=contact) nameserver_list = self._get_domain_nameservers_as_xml(domain) if not nameserver_list: raise RegistrarConnectorException( _('Nameservers for domain are required')) dom_req = E.createDomainRequest( self._xml_domain(domain), E.period(domain.registration_period), E.authCode(DomainUtils.decode_epp_code(domain.epp_code)), E.ownerHandle(owner_handle), E.adminHandle(owner_handle), E.techHandle(owner_handle), E.billingHandle(owner_handle), E.resellerHandle(''), E.nameServers(E.array(*nameserver_list))) response = self.api_request(data=dom_req) if response.data.status == 'ACT': domain.status = DomainStatus.active domain.registration_date = datetime.strptime( str(response.data.activationDate), '%Y-%m-%d %H:%M:%S').date() domain.expiry_date = datetime.strptime( str(response.data.expirationDate), '%Y-%m-%d %H:%M:%S').date() domain.epp_code = DomainUtils.encode_epp_code( str(response.data.authCode)) domain.save(update_fields=[ 'status', 'registration_date', 'expiry_date', 'epp_code' ]) return _('Domain transfered') elif response.data.status == 'REQ': domain.status = DomainStatus.pending domain.save(update_fields=['status']) return _('Domain pending registration') else: raise RegistrarConnectorException(_('Domain registration unknown'))
def validate(self, attrs): validated_data = super().validate(attrs=attrs) domain_settings = DomainsSettings.for_client( client=self.context['request'].user.clients.first()) # validate domain name if attrs['operation'] == 'register': available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_registration( domain_name=attrs['name'], domains_settings=domain_settings, skip_whois_check=True, ) if not available: raise ValidationError({'non_field_errors': error}) else: validated_data['name'] = adjusted_name if attrs['operation'] == 'transfer': available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_transfer( domain_name=attrs['non_field_errors'], domains_settings=domain_settings, skip_whois_check=True, ) if not available: raise ValidationError({'name': error}) else: validated_data['name'] = adjusted_name return validated_data
def transfer_domain(self, request: Request) -> Response: serializer = TransferDomainSerializer(data=request.data['domain']) if serializer.is_valid(raise_exception=True): client = Client.objects.get(id=serializer.validated_data['client']) domains_settings = DomainsSettings.for_client(client=client) domain_name = serializer.validated_data['name'] available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_transfer( domain_name=domain_name, domains_settings=domains_settings, skip_whois_check=True, ) if not available: Response(data={'detail': error}, status=400) else: domain_name = adjusted_name tld = DomainUtils.get_tld(domain_name=domain_name) with transaction.atomic(): user = client.users.first() if not user: user = request.user order = Order.objects.create(user=user, client=client, currency=client.currency, client_notes='', status=OrderStatus.pending) cycle = tld.register_product.cycles.filter( currency=client.currency, cycle_multiplier=serializer.validated_data['years'] + 1, ).first() plugin_data = dict(serializer.validated_data) plugin_data['operation'] = 'transfer' plugin_data['epp'] = serializer.validated_data['epp'] order_item = order.items.create( item_type=OrderItemTypes.service, product=tld.transfer_product, cycle=cycle, fixed_price=cycle.fixed_price, cycle_display=cycle.display_name, plugin_data=plugin_data, name=domain_name, description=_('Domain transfer'), ) if not validate_services_limit(): raise APIException( _('License service limit reached. Please check your license' ), ) create_service_for_item(item=order_item) return Response(data={ 'order_id': order.id, })
def is_available_for_transfer(self, request: Request) -> Response: client_id = request.query_params.get('client_id', None) client = Client.objects.get(id=client_id) domains_settings = DomainsSettings.for_client(client=client) domain_name = request.query_params.get('domain_name', None) available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_transfer( domain_name=domain_name, domains_settings=domains_settings, skip_whois_check=True, ) if not available: return Response(data={'error': error, 'available': False}) else: domain_name = adjusted_name tld = DomainUtils.get_tld(domain_name) if not tld: return Response( data={ 'error': _('Domains {} are not available for transfer'.format( DomainUtils.get_tld_name(domain_name))), 'available': False }) if not tld.transfer_product: return Response( data={ 'error': _('No price defined for {} domains'.format( tld.name)), 'available': False }) price_cycles = tld.get_prices_for_type_and_currency( price_type=PriceType.transfer, currency=client.currency) return Response( data={ 'available': True, 'adjusted_name': adjusted_name, 'prices': PriceCyclesSerializer().to_representation( instance=price_cycles), 'config': DomainsSettingsSerializer().to_representation( instance=domains_settings), 'tld': TLDSerializer().to_representation(instance=tld), })
def validate(self, attrs): validated_data = super().validate(attrs=attrs) client = self.context['request'].user.clients.first() domain_settings = DomainsSettings.for_client(client=client) # validate domain name if attrs['operation'] == 'register': available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_registration( domain_name=attrs['name'], domains_settings=domain_settings, ) if not available: raise ValidationError({'non_field_errors': error}) else: validated_data['name'] = adjusted_name contact_id = attrs.get('contact_id', 0) if contact_id is None: contact_id = 0 if contact_id == 0: missing_fields, missing_fields_labels = CustomFieldsValidator.client_has_missing_fields_for_domain( client_id=client.id, domain_name=attrs['name'], ) else: missing_fields, missing_fields_labels = CustomFieldsValidator.contact_has_missing_fields_for_domain( contact_id=contact_id, domain_name=attrs['name'], ) if missing_fields: raise ValidationError({ 'non_field_errors': _('Missing custom fields: {}. Edit client/contact.').format( ','.join(missing_fields_labels)) }) if attrs['operation'] == 'transfer': available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_transfer( domain_name=attrs['non_field_errors'], domains_settings=domain_settings, ) if not available: raise ValidationError({'name': error}) else: validated_data['name'] = adjusted_name return validated_data
def get_display_name(self, instance: Registrar): if self.price_domain_id: domain = Domain.objects.filter(id=self.price_domain_id).first() if domain: prices = DomainUtils.get_domain_registrar_prices(domain=domain, registrar=instance) price_for_action = None action = None if prices: if domain.status == DomainStatus.pending: price_for_action = prices.register_price action = _('register domain ') if domain.status == DomainStatus.pending_transfer: price_for_action = prices.transfer_price action = _('transfer domain') if domain.status == DomainStatus.active: price_for_action = prices.renew_price action = _('renew domain') if price_for_action: return _('{} - {} {} {} for {} year(s)').format( instance.name, prices.register_price if domain.status == DomainStatus.pending else prices.renew_price, prices.currency, action, domain.registration_period, ) else: return _('{} - {}').format( instance.name, _('no prices available') ) return instance.name
def initialize(self, service: Service) -> bool: """Initializes a new service object. This should be the first function called on a service. Keyword arguments: service -- the service to initialize Returns: True if service was initialized successfully """ LOG.debug('{} initialized called for service {}:{}'.format( self.module_name, service.id, service)) operation = service.plugin_data.get('operation', None) with transaction.atomic(): domain = Domain.objects.create( name=service.plugin_data['name'], status=DomainStatus.pending if operation == 'register' else DomainStatus.pending_transfer, tld=DomainUtils.get_tld( domain_name=service.plugin_data['name']), epp_code=DomainUtils.encode_epp_code( service.plugin_data.get('epp')), service=service, # TODO: this is now used instead of product data because edit item does not currently knows to update # TODO: product data registration_period=service.cycle.cycle_multiplier, ) for nameserver in [ service.plugin_data.get('nameserver1', None), service.plugin_data.get('nameserver2', None), service.plugin_data.get('nameserver3', None), service.plugin_data.get('nameserver4', None), ]: if nameserver: defaults = {'host_name': nameserver} db_nameserver, created = Nameserver.objects.get_or_create( **defaults, defaults=defaults) domain.nameservers.add(db_nameserver) contact_id = service.plugin_data.get('contact_id', None) domain.contact = Contact.objects.filter(id=contact_id).first() domain.save() return True
def transfer(self, domain: Domain) -> str: api_params = self._prepare_register_params(domain, years=1) api_params['auth-code'] = DomainUtils.decode_epp_code(domain.epp_code) api_response = self.api_request('POST', self.TRANSFER_DOMAIN_URL, api_params) message = self.get_actionstatusdesc(api_response) domain.status = DomainStatus.active domain.save(update_fields=['status']) return message
def perform_update(self, serializer: Serializer): if serializer.is_valid(raise_exception=True): previous_instance = self.get_object() # type: Domain registration_period = serializer.validated_data[ 'registration_period'] if registration_period and registration_period != previous_instance.registration_period: # registration period changed, update price cycle service = previous_instance.service new_cycle = service.product.cycles.filter( cycle_multiplier=registration_period).first() if new_cycle: service.cycle = new_cycle service.save() else: raise ValidationError({ 'registration_period': _('No price defined for this registration period. Check TLD pricing' ) }) new_name = serializer.validated_data['name'] if new_name and new_name != previous_instance.name: if not DomainUtils.validate_domain_name(domain_name=new_name): raise ValidationError({'name': _('Invalid domain name')}) try: new_tld_name = DomainUtils.get_tld_name(new_name) except ValueError: new_tld_name = None if previous_instance.tld.name != new_tld_name: raise ValidationError({ 'name': _('New domain name should have the same TLD({})'). format(previous_instance.tld.name) }) serializer.save()
def transfer(self, domain: Domain) -> str: """Transfer domain to other registrar""" params = { 'domain': domain.name, 'authorization_key': DomainUtils.decode_epp_code(domain.epp_code) } try: self.api_request(request_method=RotldActions.TRANSFER_DOMAIN, params=params) except RegistrarConnectorException as e: LOG.debug(e) return '{}'.format(e) return _('Success')
def transfer_domain(self, request: Request) -> Response: serializer = TransferDomainSerializer(data=request.data['domain']) if serializer.is_valid(raise_exception=True): user = request.user client = user.clients.first() domains_settings = DomainsSettings.for_client(client=client) domain_name = serializer.validated_data['name'] available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_transfer( domain_name=domain_name, domains_settings=domains_settings) if not available: Response(data={'detail': error}, status=400) else: domain_name = adjusted_name tld = DomainUtils.get_tld(domain_name=domain_name) cart = cart_from_request(request=self.request, create=True) cycle = tld.register_product.cycles.filter( currency=client.currency, cycle_multiplier=serializer.validated_data['years'] + 1, ).first() plugin_data = dict(serializer.validated_data) plugin_data['operation'] = 'transfer' plugin_data['epp'] = serializer.validated_data['epp'] cart.items.create( item_type=OrderItemTypes.service, product=tld.transfer_product, cycle=cycle, fixed_price=cycle.fixed_price, cycle_display=cycle.display_name, plugin_data=plugin_data, name=domain_name, description=_('Domain transfer'), ) return Response()
def generate_customer_password(length=9): """Generate a password and make sure it contains all required characters by Resellerclub""" limit = 0 password = DomainUtils.generate_password(length) while limit < 20: lowecase_found = False uppercase_found = False number_found = False punctuation_found = False for char in password: if char in string.ascii_lowercase: lowecase_found = True elif char in string.ascii_uppercase: uppercase_found = True elif char in string.digits: number_found = True elif char in string.punctuation: punctuation_found = True if lowecase_found and uppercase_found and number_found and punctuation_found: return password else: password = DomainUtils.generate_password(length) limit += 1 raise RegistrarConnectorException('Unable to generate a Customer password')
def contact_has_missing_fields_for_domain( contact_id: int, domain_name: str) -> Tuple[bool, List[str]]: tld = DomainUtils.get_tld(domain_name=domain_name) custom_fields = tld_custom_fields.get_definitions_for_tld( tld_name=tld.name, ) custom_field_names = [name for name in custom_fields] fields_with_values_in_db = ContactCustomField.objects.filter( contact_id=contact_id, ).exclude(value__isnull=True, ).exclude( value__exact='').values_list('name', flat=True) missing_fields = [ field_name for field_name in custom_field_names if field_name not in fields_with_values_in_db ] missing_field_labels = [ custom_fields[field_name]['label'] for field_name in missing_fields ] return len(missing_field_labels) > 0, missing_field_labels
def is_available_for_registration(self, request: Request) -> Response: client_id = request.query_params.get('client_id', None) client = Client.objects.get(id=client_id) domains_settings = DomainsSettings.for_client(client=client) domain_name = request.query_params.get('domain_name', None) available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_registration( domain_name=domain_name, domains_settings=domains_settings, skip_whois_check=True, ) if not available: return Response(data={'error': error, 'available': False}) else: domain_name = adjusted_name tld = DomainUtils.get_tld(domain_name) if not tld: return Response( data={ 'error': _('Domains {} are not available for registration'.format( DomainUtils.get_tld_name(domain_name))), 'available': False }) if not tld.register_product: return Response( data={ 'error': _('No price defined for {} domains'.format( tld.name)), 'available': False }) price_cycles = tld.get_prices_for_type_and_currency( price_type=PriceType.register, currency=client.currency) dns_price_cycles = tld.get_addon_prices_for_type_and_currency( price_type=AddonPriceType.dns, currency=client.currency) email_price_cycles = tld.get_addon_prices_for_type_and_currency( price_type=AddonPriceType.email, currency=client.currency) id_price_cycles = tld.get_addon_prices_for_type_and_currency( price_type=AddonPriceType.id, currency=client.currency) client_details = '{}({})\n{}, {}\n{}, {}'.format( client.name, client.email, client.address1, client.city, client.state, client.country) return Response( data={ 'client_id': client.id, 'client_details': client_details, 'available': True, 'adjusted_name': adjusted_name, 'prices': PriceCyclesSerializer().to_representation( instance=price_cycles), 'dns_prices': AddonPriceCyclesSerializer().to_representation( instance=dns_price_cycles), 'email_prices': AddonPriceCyclesSerializer().to_representation( instance=email_price_cycles), 'id_prices': AddonPriceCyclesSerializer().to_representation( instance=id_price_cycles), 'config': DomainsSettingsSerializer().to_representation( instance=domains_settings), 'tld': TLDSerializer().to_representation(instance=tld), })
def get_epp_code(self, domain: Domain): response = self._retrieve_domain(domain) auth_code = str(response.data.authCode) domain.epp_code = DomainUtils.encode_epp_code(auth_code) domain.save(update_fields=['epp_code']) return auth_code
def set_whois_data(self, domain: Domain, whois_data: List[WhoisField]) -> Tuple[bool, str]: """ Update the contact information for a domain. If the existing contact is used only for this domain and the company information is not changed, it will be updated, otherwise a new contact will be created. :param domain: The domain to set whois data for :param whois_data List of WhoisField instances :return: tuple of status and error message """ domain_sld = DomainUtils.strip_tld(domain.name) resp = self._retrieve_domain(domain=domain) owner_handle = resp.data.ownerHandle create_new_contact = False whois_fields_data = {'name': {}, 'phone': {}, 'address': {}} for wfield in whois_data: if wfield.name == 'companyName': whois_fields_data['companyName'] = wfield.value elif wfield.name == 'gender': whois_fields_data['gender'] = wfield.value elif wfield.name == 'email': whois_fields_data['email'] = wfield.value elif wfield.name == 'vat': whois_fields_data['vat'] = wfield.value elif wfield.name.startswith('flname'): name_key = wfield.name.split('flname')[1] if name_key: whois_fields_data['name'][name_key] = wfield.value elif wfield.name.startswith('fladdress'): addr_key = wfield.name.split('fladdress')[1] if addr_key: whois_fields_data['address'][addr_key] = wfield.value elif wfield.name.startswith('flphone'): phone_key = wfield.name.split('flphone')[1] if phone_key: whois_fields_data['phone'][phone_key] = wfield.value if not create_new_contact: existing_customer = self.retrieve_customer(owner_handle) if existing_customer.data.companyName != whois_fields_data.get( 'companyName'): create_new_contact = True LOG.debug('Creating new customer. Company name differs.') if not create_new_contact: # See if we actually need to create a new contact domains_used_by_handle = self._search_domain_by_contact_handle( owner_handle) # Look for company name changes for dom_used in domains_used_by_handle.results_list: if (dom_used.domain.name != domain_sld or dom_used.domain.extension != domain.tld.stripped_name): create_new_contact = True LOG.debug( 'Creating new customer. Existing one is in use by multiple domains' ) break address_details = E.address( E.street(whois_fields_data['address'].get('street', '')), E.number(whois_fields_data['address'].get('number', '')), E.zipcode(whois_fields_data['address'].get('zipcode', '')), E.city(whois_fields_data['address'].get('city', '')), E.country(whois_fields_data['address'].get('country', '')), E.state(whois_fields_data['address'].get('state', ''))) phone_details = E.phone( E.countryCode(whois_fields_data['phone'].get('countryCode', '')), E.areaCode(whois_fields_data['phone'].get('areaCode', '')), E.subscriberNumber(whois_fields_data['phone'].get( 'subscriberNumber', ''))) if not create_new_contact: modify_details = [E.email(whois_fields_data['email'])] if whois_fields_data.get('vat'): modify_details.append(E.vat(whois_fields_data['vat'])) xml_req = E.modifyCustomerRequest(E.handle(str(owner_handle)), address_details, phone_details, *modify_details) else: new_handle = self._create_customer( first_name=whois_fields_data['name']['firstName'], last_name=whois_fields_data['name']['lastName'], email=whois_fields_data['email'], address=address_details, company=whois_fields_data.get('companyName', ''), vat=whois_fields_data.get('vat', ''), phone_details=phone_details) xml_req = E.modifyDomainRequest(self._xml_domain(domain), E.ownerHandle(str(new_handle)), E.adminHandle(str(new_handle)), E.techHandle(str(new_handle)), E.billingHandle(str(new_handle))) try: self.api_request(data=xml_req) except RegistrarConnectorException as e: LOG.exception(e) return False, str(e) return True, _('Whois data updated')
def register_domain(self, request: Request) -> Response: serializer = RegisterDomainSerializer( data=request.data['domain'], context={'request': self.request}, ) if serializer.is_valid(raise_exception=True): client = Client.objects.get(id=serializer.validated_data['client']) domains_settings = DomainsSettings.for_client(client=client) domain_name = serializer.validated_data['name'] available, error, adjusted_name = DomainUtils.check_if_domains_is_available_for_registration( domain_name=domain_name, domains_settings=domains_settings, skip_whois_check=True, ) if not available: Response(data={'detail': error}, status=400) else: domain_name = adjusted_name tld = DomainUtils.get_tld(domain_name=domain_name) user = client.users.first() if not user: user = request.user order = Order.objects.create(user=user, client=client, currency=client.currency, client_notes='', status=OrderStatus.pending) cycle = tld.register_product.cycles.filter( currency=client.currency, cycle_multiplier=serializer.validated_data['years'] + 1, ).first() dns_cycle = tld.dns_option.cycles.filter( currency=client.currency, cycle_multiplier=serializer.validated_data['years'] + 1, ).first() if serializer.validated_data.get('dns_management', False) else None email_cycle = tld.email_option.cycles.filter( currency=client.currency, cycle_multiplier=serializer.validated_data['years'] + 1, ).first() if serializer.validated_data.get('email_forwarding', False) else None id_cycle = tld.id_option.cycles.filter( currency=client.currency, cycle_multiplier=serializer.validated_data['years'] + 1, ).first() if serializer.validated_data.get('id_protection', False) else None plugin_data = dict(serializer.validated_data) plugin_data['operation'] = 'register' with transaction.atomic(): order_item = order.items.create( item_type=OrderItemTypes.service, product=tld.register_product, cycle=cycle, fixed_price=cycle.fixed_price, cycle_display=cycle.display_name, plugin_data=plugin_data, name=domain_name, description=_('Domain registration'), ) if dns_cycle: OrderItemConfigurableOption.objects.create( order_item=order_item, option=tld.dns_option, option_value="yes", quantity=1, has_price=True, unit_price=dns_cycle.price, price=dns_cycle.price, setup_fee=0) if email_cycle: OrderItemConfigurableOption.objects.create( order_item=order_item, option=tld.email_option, option_value="yes", quantity=1, has_price=True, unit_price=email_cycle.price, price=email_cycle.price, setup_fee=0) if id_cycle: OrderItemConfigurableOption.objects.create( order_item=order_item, option=tld.id_option, option_value="yes", quantity=1, has_price=True, unit_price=id_cycle.price, price=id_cycle.price, setup_fee=0) if not validate_services_limit(): raise APIException( _('License service limit reached. Please check your license' ), ) create_service_for_item(item=order_item) return Response(data={ 'order_id': order.id, })
def validate_nameserver(value): if not DomainUtils.validate_domain_name(domain_name=value): raise serializers.ValidationError(_('Not a valid hostname'))
def search_domain(self, domain: Domain) -> str: api_params = {'domain-name': DomainUtils.strip_tld(domain.name), 'tlds': domain.tld.name.lstrip('.')} response = self.api_request('POST', self.DOMAIN_AVAILABLE_URL, api_params, domain_check=True) return response
def domain_name_validator(domain_name: str): if not DomainUtils.validate_domain_name(domain_name=domain_name): raise serializers.ValidationError( _('Must contain a valid domain name, containing at least a "."'))
def _xml_domain(domain: Domain): """Return an OpenXML formatted domain""" return E.domain(E.name(DomainUtils.strip_tld(domain.name)), E.extension(domain.tld.stripped_name))
def tld_name_validator(tld_name: str): if not DomainUtils.validate_tld_name(tld_name=tld_name): raise serializers.ValidationError( _('Must contain a valid tld name, starting with "."'))