U
     d2k                     @   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_VERSIONrender)self r   )/opt/account/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CmfAuthnew_from_login_hash_saltr   r   r   savedp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):accounthostname)r   r   r   printr   AUTH_SESSION_COOKIE_DOMAINjsonify_ok)r   r-   r   outresr$   redirect_to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).0regexr'   r   r   	<genexpr>t   s     z5SignupView.cloud_assign_prohibited.<locals>.<genexpr>)any)r'   Zprohibited_org_namesr   r;   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   Данный адрес нельзя зарегистрировать. Попробуйте другой.r;   uO   Доменное имя уже занято, попробуйте другое.r   rB   " 'r+   uK   Такой пользователь уже зарегистрирован. u>   Не удалось создать учётную запись  N8   Не удалось зарегистрироваться)r   r   r.   itemsr   r   _errorr	   stripr   r>   r   r   r   r
   replace__profile__r*   r   send_passwordr&   value	Exceptionlogging	exceptionstrr   r   cloud_assignr6   )r   error_messageskeymessager   r'   is_org_name_usedr   rB   r$   r)   er-   r2   r3   r   r   r   rT   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   r?   problem_fieldr+   uv   Этот e-mail уже зарегистрирован. Попробуйте другой или перейдите в z	<a href="u   ">Ваш профиль</a>NZ	lead_typeZ
email_onlyu?   Не удалось создать учётную запись.rG   u@   Не удалось создать учётную запись. ur   Не удалось отправить человеку %s пароль. Потом сам восстановит.rH   u3   Удалось зарегистрироваться)r   r   r   r   rJ   r	   r   r   r   AUTH_SERVER_URLr   r*   r   rQ   rR   __support__rN   r&   rO   r1   )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;    некорректно, попробуйте другое.rZ   r   rB   rD   rE   rF   Zlead_contact_namer;   Z    уже занято, попробуйте другое название компании.r   scoper   fieldsuE   Введён некорректный номер телефона %s.u@   Введите корректный номер телефона.uN   Не удалось обновить данные учётной записи.rG   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   jsonrK   idnaencode	IDNAErrorrJ   r   r/   r
   r   rL   r   r   r   r>   gr$   r   r   r'   r    r   CmfValidationErrorrQ   rR   rP   r]   r   r   preparebrandingrO   Z__proceed__errorr`   is_nullr\   r1   r0   )r   r'   r   rB   	user_namerX   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   Ваша учётная запись, похоже, была удалена.r@   rA   )r'   rB   rB   rD   rE   rF   r'   r   r;   r_   rZ   rC   uD   Не удалось выдать виртуальную машинуN)r   r   rh   r$   rJ   r&   rO   r   r   r   r`   groupsrp   r   rI   r   rd   rL   rK   r
   r    r/   r   r>   r   r   rT   rP   rQ   rR   r6   )r   r   r$   r   rU   rV   rW   rB   r'   rX   r-   r2   r3   errr   r   r   cloud_assign_continue  sP    


z SignupView.cloud_assign_continuec              
   C   s0  t tjd }tjdd}tjd }tj|}t|d d }zt	
|}W n* tk
r|   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}|r`|jjr>td|| | }	|jdd}
| |	|jj n td|| tj d| }
nNtd|| tj||d}| }	|rd|_|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_must_change_passwordNinvite_tokenpayloadissuJ   Не удалось прочитать публичный ключ EvaTeamrG   uN   Не удалось валидировать токен для %s от CRM %s!r   	pass_hashra   u   INVITE. Отправляем существующему пользователю {} письмо с инвайтом в crm {} и высылаем ему письмо с паролемZinvite)endpointu~   INVITE. Отправляем существующему пользователю {} письмо с инвайтом в crm {}z/auth/signin?next_url=https://uz   INVITE. Создаем пользователя {} для crm {} и высылаем ему письмо с паролем)r   r&      u&   Ссылка для доступа к zinvite_by_email.html)Z
invite_urlrH   u:   Не удалось зарегистрироваться: r   )%r	   r   r   r   r   r   rsa_unpack_jwtshlexquoter   read_crm_pub_keyRuntimeErrorrQ   rR   rJ   rsa_verify_jwtrl   lenr   r   rx   rm   r.   formatr(   reset_pass_linkrN   r&   rO   r\   password_expires_must_changePROJECT_NAMErender_with_paramsr   rP   rS   r   )r   r&   rt   ru   jwtrw   crm_pub_keyverifyr$   r)   ro   subjectmsg_contentsrY   r   r   r   invite_by_emailX  sZ    

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
        rc   zsend_password.html)r)   proceed_linku&   Пароль для доступа к N)r   r\   r   r   r   )r   r)   r&   r   r   r   r   r   r   rN     s    zSignupView.send_passwordN)__name__
__module____qualname____url__r   r/   r]   r\   rM   cmfviewsactionr   r%   staticmethodr*   r6   r>   rT   r^   rp   rs   r   rN   r   r   r   r   r      s,   


 

5
$G
>
?r   )__doc__r|   re   flaskr   	cmf.viewsr   cmf.data_providers.baser   cmf.includeZcommon.acrmr   modules.auth.views.responser   Zmodels.emailr   r	   Zmodels.phoner
   Zmodels.supervisorr   r   BaseViewr   r   r   r   r   <module>   s   