U
    ici                     @   s   d Z ddlZddlZddlmZ ddlZddlmZ ddl	T ddl
mZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ G dd dejjeZdS )u  
Документация по выдаче VM: https://bcrm.carbonsoft.ru/project/Document/DOC-000884
Если кратко:
+----------+--------+-----------------------+
|   Этап   |  View  |      Supervisor       |
+----------+--------+-----------------------+
| Register | Signup | ---                   |
| Assign   | CRM    | cloud_assign_vm.sh    |
| Prepare  | CRM    | vm_assign_prepare.sh  |
| Branding | CRM    | vm_assign_branding.sh |
+----------+--------+-----------------------+
    N)abort)commit_all_ds)*)acrm_register)ResponseMixin   )
send_emailnormalize_email_address)normalize_phone)
Supervisorc                   @   s   e Zd ZdZdej dZdej dZe	j
jdd Ze	j
jdd	 Zed
d Zdd Zedd Ze	j
jdd Ze	j
jdd Zdd Ze	j
jdd Ze	j
jdd Zdd ZdS )
SignupViewz/signupu,   Обратитесь в <a href="https://wwwu9   /support/">техническую поддержку</a>.u   Перейти в <a href="u   ">Ваш профиль</a>?c                 C   s   t jr
dS | dS )N{   Регистрация без приглашения не поддерживается в коробочной версииzsignup.html)configIS_BOX_VERSIONZrender)self r   ./modules/auth/views/signup.pyget$   s    zSignupView.getc                 C   sv   t jr
dS ttjd }tjd }tjd }tjd }tj|||}|sZtd t	d ||_
|  |j  dS )	Nr   loginhashsaltphoneznot auth  Signed up successfully)r   r   r	   requestvaluesmodelsCmfAuthZnew_from_login_hash_saltr   r   r   saveZdpZcommit)r   r   _hashr   r   authr   r   r   post*   s    



zSignupView.postc                 C   s*   t j| | ||d}| }|  ||fS )N)r   emailorg_namer   )r   r   reset_passwordr   )r   r#   r   r    passwordr   r   r   _create_auth=   s    zSignupView._create_authc                 C   sJ   t jj|d}|}|r2td| d| dtj }td|i}| ||S )u  
        TODO: избавиться от этого хака. Пока оставил для работы одноэтапной регистрации и продолжения в случае бага
        TODO: в нормальном коде мы просто отдаём "всё хорошо, всё плохо", а вызывающая сторона при необходимости
        TODO: отпралвяет нас на /auth/signin?action=proceed, где мы уже сами разрулим, куда человеку надо в зависимости
        TODO: от того что у него в куке.
        Подготавливаем ответ для лендинга/продолжения выдачи, обрабатывая ошибки вызова супервизора
        :param hostname: адрес, на который отправялем клиента
        :param login: email клиента, по нему найдём учётку, по которой выставим/удалим куки.
        :param out: выхлоп (stderr + stdout (в идеале)) от вызова супервизора по SSH.
                    По хорошему не отправлять это на фронт! По идее как-то проверять содержимое выхлопа или
                    навести порядок в кодах возврата (нет свободных VM, известная ошибка при выдаче, ошибка кодинга)
        :param res: код возврата от вызова супервизора по SSH.
        :return: ResponseMixin with a hostname to redirect user to
        r   zERROR(z):Zaccounthostname)r   r   r   printr   AUTH_SESSION_COOKIE_DOMAINjsonify_ok)r   r(   r   outresr    Zredirect_toZresponser   r   r   cloud_assign_responseD   s    
z SignupView.cloud_assign_responsec                    s   d}t  fdd|D S )N)z^node[0-9]+z	^account$z^(pd)?ns[0-9]+z^acrm[0-9]+z
^whatsapp$z^docs$z^supervisor$z^static$z^files$z^www$z^$z[.]c                 3   s   | ]}t | V  qd S )N)refindall).0Zregexr#   r   r   	<genexpr>t   s     z5SignupView.cloud_assign_prohibited.<locals>.<genexpr>)any)r#   Zprohibited_org_namesr   r3   r   cloud_assign_prohibitedd   s    z"SignupView.cloud_assign_prohibitedc              
   C   s  t jr
dS tddd ddddd}| D ]"\}}|tjkr,| d	|  S q,ttjd
 }tjd  }t	
|r| d	dS tjj|d}|r| d	dS tjd}t|}tjd dddd}tjj|d}	|	r| d	d| j S z2t	|||\}	}
tf tj | |
|	jj W nB tk
rf } z"td | dt| W Y S d}~X Y nX |	sz| d	dS t  t||||\}}}tddd | ||||S )u  
        Оригинальная версия регистрации в один этап. Сохранена для совместимости и постепенно выкатки.
        В будущем можно будет удалить.
        Запускаем все процессы и просим пользователя подождать
        15 секунд (а сами работаем секунд 20-25).
        Регистрируем пользователя и создаем виртуалку с CRM (запрос приходит с лендинга)
        :return: билеты авторизации и hostname виртуалки
        r   z=========================zcloud_assign done8   Укажите логин для регистрации.0   Укажите адрес входа для CRM.N   Укажите название компании для регистрацииuH   Укажите номер телефона для регистрации)r   r#   companyr   r   r   r#   i   Данный адрес нельзя зарегистрировать. Попробуйте другой.r3   uO   Доменное имя уже занято, попробуйте другое.r   r:   " 'r'   uK   Такой пользователь уже зарегистрирован. u>   Не удалось создать учётную запись  N8   Не удалось зарегистрироваться)r   r   r)   itemsr   r   _errorr	   stripr   r6   r   r   r   r
   replace__profile__r&   r   send_passwordr"   value	Exceptionlogging	exceptionstrr   r   cloud_assignr/   )r   error_messageskeymessager   r#   is_org_name_usedr   r:   r    r%   er(   r-   r.   r   r   r   rL   w   sJ    



&zSignupView.cloud_assignc                 C   s  t jr
dS dtjkr$| jddddS ttjd }tjj|d}|rjd}|dt j	 d	7 }| jd|ddS z*t
|d
d
\}}tf tjddi W n(   td | dd| j  Y S X z| ||jj W n   td| Y nX |s| dd| j S | d|S )u6  
        Регистрируем пользователя по одному лишь email
        Заодно создаём "отложенного" лида.
        :request.param: login - email.
        :return: билеты авторизации с пустым scope, но с логинам.
        r   r   r   r7   Zproblem_fieldr'   uv   Этот e-mail уже зарегистрирован. Попробуйте другой или перейдите в z	<a href="u   ">Ваш профиль</a>NZ	lead_typeZ
email_onlyu?   Не удалось создать учётную запись.r?   u@   Не удалось создать учётную запись. ur   Не удалось отправить человеку %s пароль. Потом сам восстановит.r@   u3   Удалось зарегистрироваться)r   r   r   r   rB   r	   r   r   r   AUTH_SERVER_URLr   r&   r   rI   rJ   __support__rF   r"   rG   r,   )r   r   r    Z
error_textr%   r   r   r   register   s.    

zSignupView.registerc              	   C   s  t jd  }zt| W n4 tjk
rP   | jdd| tj ddd Y S X t	t j
d}t jd dd	d
d	}t jd  }tjj
|d}|r| jd| tj dddS t|r| jd| tj dddS tjj
tjjddddgd}z$||_||_|  tf t j W n\ tk
rP   td| | jdddd Y S  tk
rz   td | dd Y S X |s| dd| j S t  zt| W n   td Y nX zt|||jj || W n(   td | dd| j!  Y S X tjj
tjjd}|s:t"d | dd| j S |j#j$rbt"d | dd| j S tj%dd	d d	}| &t'd!|d" i|S )#Nr#   r   u   Доменное имя u;    некорректно, попробуйте другое.rR   r   r:   r<   r=   r>   Zlead_contact_namer3   Z    уже занято, попробуйте другое название компании.r   scoper   ZfieldsuE   Введён некорректный номер телефона %s.u@   Введите корректный номер телефона.uN   Не удалось обновить данные учётной записи.r?   u   Не удалось обновить данные учётной записи. Пожалуйста, повторите попытку.u:   Не удалось зарегистрироваться. ug   Произошла ошибка при prepare VM, возможно prepare уже выполнялсяuD   Произошла ошибка при брендировании VMu'   Ошибка сервера. Код #6.r'   uq   Пользователь пропал из БД в процессе выдачи ВМ. Надо дебажить.u(   Ошибка сервера. Код #7. uy   Такое бывает при замаскированной ошибке в процессе CmfPerson.sync_accounts().u(   Ошибка сервера. Код #8. zhttps://zhttp://r(   /auth/signin?action=proceed)(r   jsonrC   idnaencodeZ	IDNAErrorrB   r   r*   r
   r   rD   r   r   r   r6   gr    r   r   r#   r   r   ZCmfValidationErrorrI   rJ   rH   rT   r   r   ZprepareZbrandingrG   Z__proceed__errorrW   is_nullrS   r,   r+   )r   r#   r   r:   Z	user_namerP   r    urlr   r   r   )_cloud_assign_continue_crm_already_exists   s    







z4SignupView._cloud_assign_continue_crm_already_existsc              
   C   s  t jr
dS tjs| ddS tjjj}tjj	|d}|sD| ddS |j
sP|jrX|  S |jj}ddd}| D ]$\}}tj	|sr| d|  S qrtjd	 d
ddd}tjd  }|stj	drtj	d}t|}||_|  tjj	|d}	|	r"| jd| t j dddS t|r:| ddS t  zt||||\}
}}W n2 tk
r } ztd |W 5 d}~X Y nX | |
|||S )u  
        Запрос приходит от авторизованного пользователя из account.evacrm.ru
        Позволяем продолжить выдачу виртуалки в случае если первая попытка провалилась, но учётку создали
        Не отправляем запрос напрямую в cloud_assign_supervisor_call, здесь валидируем то что:
        1. Юзер авторизован.
        2. Его учётка есть в БД.
        3. У него нет виртуалки (иногда происходит, сделали хак _cloud_assign_continue_crm_already_exists).
        r   r   uV   Зарегистрируйтесь, чтобы получить демо-версию.r'   uL   Ваша учётная запись, похоже, была удалена.r8   r9   )r#   r:   r:   r<   r=   r>   r#   r   r3   rV   rR   r;   uD   Не удалось выдать виртуальную машинуN)r   r   r]   r    rB   r"   rG   r   r   r   rW   groupsra   r   rA   r   rZ   rD   rC   r
   r   r*   r   r6   r   r   rL   rH   rI   rJ   r/   )r   r   r    r   rM   rN   rO   r:   r#   rP   r(   r-   r.   errr   r   r   cloud_assign_continue  sP    


z SignupView.cloud_assign_continuec              
   C   s  t tjd }tjd }tj|}t|d d }zt	|}W n* t
k
rn   td | dd Y S X tj||}|std|| ||dt|d	  |dt|d	   krtjr|dt|d	  }ztjj|d
gd}|rR|jjr0td|| | }|jdd}	| ||jj n td|| tj d| }	nBtd|| tj||d}| }|jdd}	| ||jj dtj }
| jd|	dg}t ||
|jj W nH t!k
r
 } z(td | ddt"|  W Y S d}~X Y nX t#  dS )u   
        Приглашение по email. В эту функцию долбится CRM с уже подготовленным JWT-токеном.
        :return:
        r"   invite_tokenZpayloadissuJ   Не удалось прочитать публичный ключ EvaTeamr?   uN   Не удалось валидировать токен для %s от CRM %s!Nr   	pass_hashrX   u   INVITE. Отправляем существующему пользователю {} письмо с инвайтом в crm {} и высылаем ему письмо с паролемZinvite)Zendpointu~   INVITE. Отправляем существующему пользователю {} письмо с инвайтом в crm {}z/auth/signin?next_url=https://uz   INVITE. Создаем пользователя {} для crm {} и высылаем ему письмо с паролем)r   r"   u&   Ссылка для доступа к zinvite_by_email.html)Z
invite_urlr@   u:   Не удалось зарегистрироваться: r   )$r	   r   r   r   r   Zrsa_unpack_jwtshlexZquoter   Zread_crm_pub_keyRuntimeErrorrI   rJ   rB   Zrsa_verify_jwtr^   lenr   r   r   rg   r_   r)   formatr$   Zreset_pass_linkrF   r"   rG   rS   PROJECT_NAMErender_with_paramsr   rH   rK   r   )r   r"   re   Zjwtrf   Zcrm_pub_keyZverifyr    r%   r`   subjectmsg_contentsrQ   r   r   r   invite_by_emailX  sT    

2
 
,zSignupView.invite_by_emailc                 C   s8   t j d}| jd||d}dt j }t||| dS )u   
        Некрасивый дубль models.CmfAuth.send_password(), потому что неясно как делать вызов View -> Model -> View
        rY   zsend_password.html)r%   proceed_linku&   Пароль для доступа к N)r   rS   rm   rl   r   )r   r%   r"   rq   ro   rn   r   r   r   rF     s    zSignupView.send_passwordN)__name__
__module____qualname__Z__url__r   r*   rT   rS   rE   cmfviewsactionr   r!   staticmethodr&   r/   r6   rL   rU   ra   rd   rp   rF   r   r   r   r   r      s,   


 

5
$G
>
;r   )__doc__rh   r[   Zflaskr   Z	cmf.viewsru   Zcmf.data_providers.baser   Zcmf.includeZcommon.acrmr   Zmodules.auth.views.responser   Zmodels.emailr   r	   Zmodels.phoner
   Zmodels.supervisorr   rv   ZBaseViewr   r   r   r   r   <module>   s   