
    Bi`              
       Z   d dl mZmZmZmZmZmZ d dlmZm	Z	 d dl
mZmZmZ d dlZd dlZd dlZd dlmZmZ d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dlZd dlZd d	lmZm Z  d d
l!m"Z" d dl#m$Z$m%Z%m&Z&m'Z'  ede(          Z)i Z*i Z+d Z,d Z- ej.        d           ej.        d           ej.        d e-             d          dddd ej.        d           ej.        d           ej.        d e-             d          dddg d ej.        d           ej.        d            ej.        d! e-             d"          d#d$d%d&d'gdd(Z/d) Z0 e0             d* Z1e)2                    d+d,g-          d.             Z3 e4            Z5e)2                    d/d,d0g-          d1             Z6d2 Z7d3 Z8d4 Z9d5 Z:d6 Z;e)2                    d7d0g-          d8             Z<e)2                    d9d0g-          d:             Z=e)2                    d;d0g-          d<             Z>e)2                    d=d,g-          d>             Z?e)2                    d?d,g-          d@             Z@e)2                    dAd0g-          dB             ZAe)2                    dCd0g-          dD             ZBe)2                    dEd0g-          dF             ZCdG ZDdH ZEe)2                    dId0g-          dJ             ZFe)2                    dKd0g-          dL             ZGe)2                    dMd0g-          dN             ZHdS )O    )	Blueprintrequestjsonifysessioncurrent_appmake_response)dbUser)UserProfileOAuthAccountOAuthProviderN)datetime	timedelta)MIMEText)MIMEMultipart)generate_password_hash)	urlencodequote)env)get_user_by_session_value"allocate_unique_user_id_from_emailallocate_unique_user_id_oauthresolve_user_refauthc                 B   	 t          j        dt          j        dd          | d          }|                                }t          d|            |                    dd          S # t          $ r*}t          d	t          |                      Y d
}~dS d
}~ww xY w)u   hCaptcha 토큰 검증zhttps://hcaptcha.com/siteverifyHCAPTCHA_SECRET_KEY*0x0000000000000000000000000000000000000000)secretresponse)datau   hCaptcha 검증 결과: successFu   hCaptcha 검증 오류: N)	requestspostosgetenvjsonprintget	Exceptionstr)tokenr   resultes       H/var/www/html/web/mlink/mlink_AI_Server/mlink-backend/src/routes/auth.pyverify_hcaptchar/   !   s    =!Bi 57cddJ
 J
   
 111222zz)U+++   1Q11222uuuuus   A'A* *
B4BBc                  h    t           j                            d          } | r| S t          j        rdS dS )u&   프론트엔드 URL 반환 (환경별)	FRONT_URLzhttps://mlink.sellmall.co.krzhttp://localhost:3001)r$   environr(   r   is_production)	front_urls    r.   get_front_urlr5   3   s:    
{++I 
 .--""    KAKAO_CLIENT_IDKAKAO_CLIENT_SECRETKAKAO_REDIRECT_URIz/auth/oauth/kakao/callbackz'https://kauth.kakao.com/oauth/authorizez#https://kauth.kakao.com/oauth/tokenz!https://kapi.kakao.com/v2/user/me)	client_idclient_secretredirect_uriauth_url	token_urluser_info_urlNAVER_CLIENT_IDNAVER_CLIENT_SECRETNAVER_REDIRECT_URIz/auth/oauth/naver/callbackz(https://nid.naver.com/oauth2.0/authorizez$https://nid.naver.com/oauth2.0/tokenz#https://openapi.naver.com/v1/nid/me)r:   r;   r<   r=   r>   r?   scopeGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URIz/auth/oauth/google/callbackz,https://accounts.google.com/o/oauth2/v2/authz#https://oauth2.googleapis.com/tokenz-https://www.googleapis.com/oauth2/v2/userinfoemailprofile)kakaonavergooglec                     g } t                                           D ]i\  }}|d         s*|                     |                                 d           |d         s*|                     |                                 d           j| r6t	          dd                    |                       t	          d           dS t	          d	           d
S )u   OAuth 설정 검증r:   
_CLIENT_IDr;   _CLIENT_SECRETu<   ⚠️  OAuth 환경변수가 설정되지 않았습니다: z, uN   📝 .env 파일을 생성하고 필요한 환경변수를 설정해주세요.Fu7   ✅ OAuth 환경변수가 모두 설정되었습니다.T)OAUTH_CONFIGitemsappendupperr'   join)missing_varsproviderconfigs      r.   validate_oauth_configrW   \   s    L(..00 E E&k" 	A8>>#3#3 ? ? ?@@@o& 	E8>>#3#3 C C CDDD fTYYWcMdMdffggg^___u	
CDDD4r6   c                  N    t          j        d                                          S )N   )r$   urandomhex r6   r.   _generate_stater]   q   s    :b>>r6   z /api/auth/oauth/<provider>/loginGET)methodsc                    | t           vrt          ddi          dfS dt          v rt          d= dt          v rt          d= t           |          }t                      }|t          d|  <   |d         |d         d	|d
}| dk    r4d                    |                    dddg                    |d<   d|d<   n| dk    r	 t          |t                    }|d          d| }t          d|i          S )u   OAuth 로그인 URL 생성error-   지원하지 않는 OAuth 제공자입니다.  user_idusernameoauth_state_r:   r<   code)r:   r<   response_typestaterK    rC   rG   rH   offlineaccess_typerJ   )	quote_viar=   ?)rO   r   r   r]   rS   r(   r   r   )rU   rV   ri   paramsqueryr=   s         r.   oauth_loginrq   u   s0    |##!PQRRTWWW GIWJ(#F E).G%8%%& K(~.	 F 8((6::g7K#L#LMMw )} 
W		 f...E$..u..HJ)***r6   z#/api/auth/oauth/<provider>/callbackPOSTc                    t          d|  d           t          dt          j                    t          dt          t          j                              | t
          vr%t          d|             t          ddi          dfS t          j        d	k    rt          j                            d
          }t          j                            d          }t          j                            d          }|r| dk    r|t          d|  <   |rt          d|            d}|dddifS n^t          j
                    pi }|                    d
          }|                    d          }|s| dk    rt          j        d|            }t          d|rdnd d|            |s;t          d           t          j        d	k    r	d}|dddifS t          ddi          dfS |t          v rt          d|dd          d           t          j        dk    rt          j        d          rt          dt          j        d                      	 dd lm} t          t          j        d                    }|r=t          d!|j                    t          d"|                                d#          d$fS n6# t"          $ r)}t          d%t%          |                      Y d}~nd}~ww xY wt          dd&i          dfS t                              |           	 t          d'|             t          d(|dd          d           t          d)           t)          | |          }	|	s%t          d*|             t          j        dk    rt          j        d          rt          d+t          j        d                      	 dd lm} t          t          j        d                    }|r=t          d!|j                    t          d"|                                d#          d$fS n6# t"          $ r)}t          d%t%          |                      Y d}~nd}~ww xY wt                              |           t          dd,i          dfS t          d-|             t          d.|	            t          d/           t-          | |	d0                   }
|
s?t          d1|             t                              |           t          dd2i          dfS t          d3|             t          d4|
            t          d5           t/          | |
|	          }|s-t                              |           t          dd6i          d7fS t          j                     |j        t          d<   |j        t          d8<   d9t          _        t          d:|  d;|j                    t          d<t          j        d           d=t          j        d8                      t                              |           t          j        d	k    r1t7                      }d>|j         d?|j         d@| dA|  dB| dC}|d$ddifS t          d"|                                d#          d$fS # t"          $ r}t          dD|  dEt%          |                      ddl}t          dF|                                            dGt%          |          v rdHt%          |          v rdI}ndDt%          |           }t                              |           t          j        d	k    rdJ| dK}|d7ddifcY d}~S t          d|i          d7fcY d}~S d}~ww xY w)Lu   OAuth 콜백 처리u   === OAuth 콜백 시작: z ===u   요청 메서드: u   요청 헤더: u%   지원하지 않는 OAuth 제공자: ra   rb   rc   r^   rg   ri   rJ   rf   u   OAuth 에러: u]  
                <!DOCTYPE html>
                <html lang="ko">
                <head>
                    <meta charset="UTF-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                    <title>로그인 실패</title>
                    <style>
                        body {
                            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            min-height: 100vh;
                            margin: 0;
                            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
                            color: #333;
                        }
                        .container {
                            background: white;
                            border-radius: 16px;
                            padding: 40px;
                            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                            text-align: center;
                            max-width: 400px;
                            width: 90%;
                        }
                        .error-icon {
                            width: 80px;
                            height: 80px;
                            margin: 0 auto 20px;
                            background: #ef4444;
                            border-radius: 50%;
                            display: flex;
                            align-items: center;
                            justify-content: center;
                            font-size: 40px;
                            color: white;
                        }
                        h1 {
                            margin: 0 0 10px;
                            font-size: 24px;
                            font-weight: 600;
                            color: #1f2937;
                        }
                        p {
                            margin: 0 0 20px;
                            color: #6b7280;
                            font-size: 14px;
                        }
                    </style>
                </head>
                <body>
                    <div class="container">
                        <div class="error-icon">✕</div>
                        <h1>로그인 실패</h1>
                        <p>인증 과정에서 오류가 발생했습니다.</p>
                        <script>
                            if (window.opener) {
                                setTimeout(() => {
                                    window.close();
                                }, 5000);
                            }
                        </script>
                    </div>
                    </body>
                </html>
                Content-Typeztext/html; charset=utf-8u   요청 데이터: code=u   있음u   없음z, state=u   인증 코드가 없습니다.uH
  
            <!DOCTYPE html>
            <html lang="ko">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>로그인 실패</title>
                <style>
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
                        color: #333;
                    }
                    .container {
                        background: white;
                        border-radius: 16px;
                        padding: 40px;
                        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                        text-align: center;
                        max-width: 400px;
                        width: 90%;
                    }
                    .error-icon {
                        width: 80px;
                        height: 80px;
                        margin: 0 auto 20px;
                        background: #ef4444;
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        font-size: 40px;
                        color: white;
                    }
                    h1 {
                        margin: 0 0 10px;
                        font-size: 24px;
                        font-weight: 600;
                        color: #1f2937;
                    }
                    p {
                        margin: 0 0 20px;
                        color: #6b7280;
                        font-size: 14px;
                    }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="error-icon">✕</div>
                    <h1>로그인 실패</h1>
                    <p>인증 코드를 받을 수 없었습니다.</p>
                    <script>
                        if (window.opener) {
                            setTimeout(() => {
                                window.close();
                            }, 5000);
                        }
                    </script>
                </div>
            </body>
            </html>
            u"   이미 처리된 코드입니다: N   z...rr   rd   uH   코드가 이미 처리되었지만 세션이 유효합니다. user_id: r   )r
   u(   세션 기반 로그인 성공: user_id=u   OAuth 로그인 성공messageuser   u'   세션 기반 사용자 조회 실패: u(   이미 처리된 인증 코드입니다.u   OAuth 콜백 처리 시작: u   인증 코드: u   === 토큰 획득 시작 ===u   토큰 획득 실패: uH   코드가 이미 사용되었지만 세션이 유효합니다. user_id: u$   토큰 획득에 실패했습니다.u   토큰 획득 성공: u   토큰 데이터: u&   === 사용자 정보 획득 시작 ===access_tokenu    사용자 정보 획득 실패: u.   사용자 정보 획득에 실패했습니다.u    사용자 정보 획득 성공: u   사용자 정보: u)   === 사용자 생성/로그인 시작 ===uI   OAuth 로그인 처리에 실패했습니다. 다시 시도해 주세요.  re   Tu   OAuth 로그인 성공: z, user_id: u   세션 정보: user_id=z, username=u!  
            <!DOCTYPE html>
            <html lang="ko">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>로그인 완료</title>
                <style>
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        color: #333;
                    }
                    .container {
                        background: white;
                        border-radius: 16px;
                        padding: 40px;
                        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                        text-align: center;
                        max-width: 400px;
                        width: 90%;
                    }
                    .success-icon {
                        width: 80px;
                        height: 80px;
                        margin: 0 auto 20px;
                        background: #10b981;
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        animation: scaleIn 0.5s ease-out;
                    }
                    .checkmark {
                        width: 40px;
                        height: 40px;
                        stroke: white;
                        stroke-width: 4;
                        stroke-linecap: round;
                        stroke-linejoin: round;
                        fill: none;
                    }
                    @keyframes scaleIn {
                        from {
                            transform: scale(0);
                        }
                        to {
                            transform: scale(1);
                        }
                    }
                    h1 {
                        margin: 0 0 10px;
                        font-size: 24px;
                        font-weight: 600;
                        color: #1f2937;
                    }
                    p {
                        margin: 0 0 20px;
                        color: #6b7280;
                        font-size: 14px;
                    }
                    .user-info {
                        background: #f9fafb;
                        border-radius: 8px;
                        padding: 16px;
                        margin: 20px 0;
                        text-align: left;
                    }
                    .user-info-item {
                        display: flex;
                        justify-content: space-between;
                        padding: 8px 0;
                        border-bottom: 1px solid #e5e7eb;
                    }
                    .user-info-item:last-child {
                        border-bottom: none;
                    }
                    .label {
                        font-weight: 500;
                        color: #6b7280;
                        font-size: 13px;
                    }
                    .value {
                        color: #1f2937;
                        font-size: 13px;
                    }
                    .message {
                        color: #10b981;
                        font-size: 13px;
                        margin-top: 16px;
                        font-weight: 500;
                    }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="success-icon">
                        <svg class="checkmark" viewBox="0 0 52 52">
                            <path d="M14.1 27.2l7.1 7.2 16.7-16.8" stroke-dasharray="100" stroke-dashoffset="100">
                                <animate attributeName="stroke-dashoffset" values="100;0" dur="0.6s" fill="freeze"/>
                            </path>
                        </svg>
                    </div>
                    <h1>로그인 완료</h1>
                    <p>성공적으로 로그인되었습니다.</p>
                    <div class="user-info">
                        <div class="user-info-item">
                            <span class="label">이메일</span>
                            <span class="value">u   </span>
                        </div>
                        <div class="user-info-item">
                            <span class="label">사용자명</span>
                            <span class="value">u  </span>
                        </div>
                    </div>
                    <p class="message">잠시 후 창이 자동으로 닫힙니다.</p>
                    <script>
                        // 부모 창에 메시지 전송
                        if (window.opener) {
                            window.opener.postMessage({
                                type: 'oauth_callback',
                                code: 'z.',
                                provider: 'u!  ',
                                success: true
                            }, window.location.origin);
                            
                            // 5초 후 창 닫기
                            setTimeout(() => {
                                window.close();
                            }, 5000);
                        } else {
                            // 팝업이 아닌 경우 메인 페이지로 리다이렉트
                            setTimeout(() => {
                                window.location.href = 'z';
                            }, 5000);
                        }
                    </script>
                </div>
            </body>
            </html>
            u   OAuth 로그인 실패: z	, error: u   에러 상세: Duplicate entry
user.emailuZ   이미 가입된 이메일 주소입니다. 다른 로그인 방법을 사용해주세요.uD
  
            <!DOCTYPE html>
            <html lang="ko">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>로그인 실패</title>
                <style>
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
                        color: #333;
                    }
                    .container {
                        background: white;
                        border-radius: 16px;
                        padding: 40px;
                        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                        text-align: center;
                        max-width: 400px;
                        width: 90%;
                    }
                    .error-icon {
                        width: 80px;
                        height: 80px;
                        margin: 0 auto 20px;
                        background: #ef4444;
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        font-size: 40px;
                        color: white;
                    }
                    h1 {
                        margin: 0 0 10px;
                        font-size: 24px;
                        font-weight: 600;
                        color: #1f2937;
                    }
                    p {
                        margin: 0 0 20px;
                        color: #6b7280;
                        font-size: 14px;
                    }
                    .error-message {
                        background: #fef2f2;
                        border: 1px solid #fecaca;
                        border-radius: 8px;
                        padding: 12px;
                        margin: 20px 0;
                        color: #dc2626;
                        font-size: 13px;
                    }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="error-icon">✕</div>
                    <h1>로그인 실패</h1>
                    <div class="error-message">aY  </div>
                    <script>
                        if (window.opener) {
                            setTimeout(() => {
                                window.close();
                            }, 5000);
                        }
                    </script>
                </div>
            </body>
            </html>
            )r'   r   methoddictheadersrO   r   argsr(   r   get_jsonprocessed_codessrc.models.userr
   r   rd   to_dictr)   r*   addget_oauth_tokendiscardget_oauth_user_infocreate_or_login_oauth_userclearre   	permanentr5   rG   	traceback
format_exc)rU   rg   ri   ra   htmlr    r
   rx   r-   
token_data	user_infor4   r   error_messages                 r.   oauth_callbackr      s\	    

4h
4
4
4555	
/w~
/
/000	
3D11
3
3444|##@h@@AAA!PQRRTWWW ~|''  ))  ))  	7X((16G-8--. G	K*5**+++CDH ~/IJJJOG	KR !!'Rxx!!  	;W,,K 9x 9 9::E	
S$BHH(
S
SE
S
STTT II.///>U""CDH ~/IJJJ!ABCCSHH A49AAABBB>V##I(>(>#u]d]hir]s]suuvvv
J0000000Y1G1GHH ST\SSTTT"#; $$ $      J J JHAHHIIIIIIIIJ!KLMMsRR D67X77888.SbS	.../// 	,---$Xt44
 	S5855666 ~''GK	,B,B'yahalmvawawyyzzzN4444444W[5K5KLLD  WWWXXX&'?$(LLNN( (            ! N N NLCFFLLMMMMMMMMN ##D)))G%KLMMsRR1x11222/://000 	6777'*^2LMM	 	]?X??@@@##D)))G%UVWWY\\\;;;<<<.9../// 	9:::)(IzJJ 	x##D)))G%pqrrtwww 	 "\	"m
 LLLdlLLMMMdI(>(>dd7;WaKbKbddeee 	%%% >U""%IQb 26cQ Qj 26kQ Q| )-}Q Q~ -5Q QT :CUQ Q QDd ~/IJJJ /LLNN
 
    	
  _6 _6 _6DDDCFFDDEEE8	 4 4 6 688999 A&&<3q66+A+AxMM?s1vv??M 	%%% >U""LB 1>CL L LDZ ~/IJJJJJJJJ/00#5555555_6s   	A%J0 0
K#:KK#B)Z >A%P% $Z %
Q/QZ Q/Z B	Z A2Z C*Z 0%Z 
]: B7]5]:]5/]:5]:c                    t           |          }|d         |d         |dd}| dk    r|d         |d<   nH| dk    r1dd	lm}  |j        d
|            }|r||d<   n!t	          d           n| dk    r|d         |d<   ddi}t	          d|            t	          d|d                     t          j        |d         ||          }t	          d|j                    t	          d|j                    |j        dk    rF|	                                }d|v rt	          d|            dS d|vrt	          d|            dS |S |j        dk    rP|	                                }	|	                    d          dv rt	          d           dS t	          d|	            dS t	          d |j         d!|j                    dS )"u   OAuth 액세스 토큰 획득r:   r;   authorization_code)r:   r;   rg   
grant_typerI   r<   rJ   r   )r   rf   ri   u2   경고: 네이버 state가 세션에 없습니다.rK   rt   z!application/x-www-form-urlencodedu   토큰 요청 데이터: u   토큰 URL: r>   )r    r   u   토큰 응답 상태: u   토큰 응답 내용: ry   ra   u?   OAuth 토큰 요청 실패 (200 응답이지만 error 포함): Nrz   u5   OAuth 토큰 응답에 access_token이 없습니다: rc   )invalid_grantinvalid_requestu@   OAuth 코드가 이미 사용되었거나 만료되었습니다.u   OAuth 토큰 요청 실패: u   토큰 요청 실패:  - )
rO   flaskr   r(   r'   r"   r#   status_codetextr&   )
rU   rg   rV   r   r   ri   r   r   token_response
error_datas
             r.   r   r     sZ   (#F K(0*	 J 7%+N%;
>""	W		
 	"!!!!!585566 	H"'Jw FGGGG	X		%+N%;
>" 	;G 

2j
2
2333	
.,
.
.///}VK0z7SSSH	
98#7
9
9:::	
28=
2
2333s""!n$$dTbddeee4//Z.ZZ[[[4			$	$]]__
>>'""&JJJTUUU4===>>>4Ox';OOOOPPPtr6   c                    t           |          }i }| dk    r	d| |d<   n| dk    r	d| |d<   n| dk    rd| |d<   t          d|d                     t          d|            t          j        |d         |	          }t          d
|j                    t          d|j                    |j        dk    r|                                S t          d|j         d|j                    dS )u   OAuth 사용자 정보 획득rI   zBearer AuthorizationrJ   rK   u   사용자 정보 요청 URL: r?   u    사용자 정보 요청 헤더: )r   u    사용자 정보 응답 상태: u    사용자 정보 응답 내용: ry   u    사용자 정보 요청 실패: r   N)rO   r'   r"   r(   r   r   r&   )rU   rz   rV   r   r   s        r.   r   r     s2   (#FG7#;\#;#;  	W		#;\#;#;  	X		#;\#;#; 	
C&*A
C
CDDD	
6W
6
6777|F?3WEEEH	
CX-A
C
CDDD	
<X]
<
<===s""}}Y1EYY(-YYZZZtr6   c           	         t          |           }| dk    rmt          |d                   }|                    di                               d          }|                    di                               dd|           }nN| dk    rt          |d	         d                   }|d	                             d          }|d	                             dd
|           }t          |          dk    rFddl} |j        |                                                                          dd         }	d
|	 }n|}n| dk    rt          |d                   }|d         }|                    dd|           }t          |          dk    rFddl} |j        |                                                                          dd         }	d|	 }n|}t          j	        
                    ||                                          }
|
r|
j        }|Nt          d           t          j                            |
           t          j                                         nG|j        }|t'          |j                  }|b|r`t*          j	        
                    |                                          }|r,|j        |_        t          j                                         |}|t/          d          |d         |
_        |                    d          |
_        d|v rR|                    dd          }t5          j                    t9          t;          |d                             z   |
_        t5          j                    |
_        t          j                                         |S |rqt*          j	        
                    |                                          }|r<t          d| d|j                     |j!        }|sRtE          |j                  }t          j        #                    |           t          j                                         t          |j         |||d         |                    d                    }
d|v rR|                    dd          }t5          j                    t9          t;          |d                             z   |
_        t          j        #                    |
           t          j                                         |S tI          | ||          }|r|n| d}t+          |||d           }|%                    d!t          t5          j                    &                                          z              t          j        #                    |           t          j                                         tE          |j                  }t          j        #                    |           t          j                                         t          |j         |||d         |                    d                    }
d|v rR|                    dd          }t5          j                    t9          t;          |d                             z   |
_        t          j        #                    |
           	 t          j                                         	 dd"l'm(}  ||j                  }|                    d#          rt          d$|j         d%           n%t          d&|                    d'                      n6# tR          $ r)}t          d(t          |                      Y d}~nd}~ww xY wn# tR          $ r}t          j        *                                 t          d)t          |                      d*t          |          v r^d+t          |          v rMt*          j	        
                    |                                          }|rt          d,|            |cY d}~S |d}~ww xY w|S )-u'   OAuth 사용자 생성 또는 로그인rI   idkakao_accountrG   
propertiesnicknamekakao_rJ   r   naver_ry   r   NrY   rK   namegoogle_)rU   provider_user_iduZ   경고: OAuthAccount에 연결된 UserProfile이 없음 — 레코드 삭제 후 재연결rG   u   OAuth 계정은 있으나 연결된 사용자를 찾을 수 없습니다. 관리자에게 문의하거나 이메일 로그인을 이용해 주세요.rz   refresh_token
expires_in)secondsu#   기존 이메일 사용자 발견: u   , 기존 사용자 ID: )rd   )user_profile_idrU   r   rz   r   z@oauth.internalT)rd   re   rG   	is_activeoauth_temp_password_add_signup_bonusr!   u>   OAuth 회원가입 보너스 크레딧 지급 완료: user_id=, amount=1000u6   OAuth 회원가입 보너스 크레딧 지급 실패: ra   uC   OAuth 회원가입 보너스 크레딧 지급 중 오류 (무시): u*   OAuth 사용자 생성 중 오류 발생: r|   r}   uB   중복 이메일로 인한 오류, 기존 사용자로 로그인: )+r   r*   r(   lenhashlibsha256encode	hexdigestr   rp   	filter_byfirstuser_profiler'   r	   r   deletecommitrx   r   rd   r
   flush
ValueErrorrz   r   r   nowr   int
expires_at
updated_atr   rH   r   r   r   set_password	timestampsrc.utils.credit_managerr   r)   rollback)rU   r   r   provider_enumr   rG   re   raw_usernamer   username_hashoauth_accountrH   rx   existingr   existing_useruid	eff_emailr   bonus_resultr-   s                        r.   r   r     s8   !(++M 7y//or2266w??==r2266zC^L\C^C^__	W		y4T:;;*%))'22 ,00=XFV=X=XYY|s""NNN*GN<+>+>+@+@AAKKMMcrcRM///HH#HH	X		y//'" }}V-I7G-I-IJJ|s""NNN*GN<+>+>+@+@AAKKMMcrcRM000HH#H !&00) 1   egg 
  ,?noooJm,,,J <D|'88||://e/<<BBDD $&.&6GOJ$$&&&#D| b   *4N)CM&*4..*I*IM'z))'^^L!<<
+3<>>IcR\]iRjNkNk<l<l<l+l('/|~~M$JK  !
,,5,99??AA 	!hhhVcVfhhiii $+G #%m.CDDD
w'''
  """ ) '
&!1'7(nn_==  M z))'^^L!<<
+3<>>IcR\]iRjNkNk<l<l<l+l(JNN=)))J   (2BE
J
JC;s$;$;$;I	  D 	,s8<>>3K3K3M3M/N/NNOOOJNN4J $,///GJNN7J !
)/ nn_55  M z!!^^L!44
#+<>>Ic*UaJbFcFc4d4d4d#d JNN=!!!

	bAAAAAA++DL99L	** lrW[Wcrrrssssj|O_O_`gOhOhjjkkk 	b 	b 	b`X[\]X^X^``aaaaaaaa	b  
 
 


C3q66CCDDDA&&<3q66+A+A J00u0==CCEEM %b[`bbccc$$$$$$$
 KsP   ^ $A)] ^ 
^]<7^ <^^ 
aB&`=5a;`==ac                 4    d}t          j        ||           d uS )Nz0^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)rematch)rG   patterns     r.   validate_emailr     s    AG8GU##4//r6   c                     t          |           dk     rdS t          j        d|           sdS t          j        d|           sdS dS )N   Fz[A-Za-z]z\dT)r   r   search)passwords    r.   validate_passwordr     sO    
8}}qu9[(++ u9UH%% u4r6   z/api/auth/registerc                     	 t          j                    } | st          ddi          dfS |                     dd                                          }|                     dd                                          }|                     d          pd                                }|r|r|st          ddi          dfS t          |          d	k     rt          dd
i          dfS t          |          st          ddi          dfS t          |          st          ddi          dfS t          j	        
                    |                                          }|rt          ddi          dfS t          j	        
                    |                                          }|rt          ddi          dfS t          ||          }t          |||          }|                    |           t          j                            |           t          j                                         	 ddlm}  ||j                  }	|	                    d          rt+          d|j         d           n%t+          d|	                    d                      n6# t,          $ r)}
t+          dt/          |
                      Y d }
~
nd }
~
ww xY wt          d|                                d          dfS # t,          $ rj}
t          j                                         t+          dt/          |
                      t          ddt/          |
           i          dfcY d }
~
S d }
~
ww xY w)Nra      데이터가 필요합니다.rc   re    rG   r   u$   모든 필드를 입력해주세요.   u/   사용자명은 3자 이상이어야 합니다.+   올바른 이메일 형식이 아닙니다.uP   비밀번호는 8자 이상이며 영문자와 숫자를 포함해야 합니다.re   +   이미 사용 중인 사용자명입니다.r   u(   이미 사용 중인 이메일입니다.)rd   re   rG   r   r   r!   8   회원가입 보너스 크레딧 지급 완료: user_id=r   0   회원가입 보너스 크레딧 지급 실패: =   회원가입 보너스 크레딧 지급 중 오류 (무시): &   회원가입이 완료되었습니다.rv      u   회원가입 오류: u%   서버 오류가 발생했습니다: r{   )r   r   r   r(   stripr   r   r   r
   rp   r   r   r   r   r	   r   r   r   r   r   rd   r'   r)   r*   r   r   )r    re   rG   r   r   existing_emailr   rx   r   r   r-   s              r.   registerr     s   <Y!! 	LG%DEFFKK88J++1133"%%++--HHZ((.B5577  	Su 	SH 	SG%KLMMsRRx==1G%VWXXZ]]]e$$ 	ZG%RSTTVYYY ** 	G%wxyy{~~~ 
,,h,??EEGG 	ZG%RSTTVYYY--E-::@@BB 	WG%OPQQSVVV 1AAC(%@@@(###

t

	\AAAAAA++DL99L	** flQUQ]lllmmmmdIYIYZaIbIbddeee 	\ 	\ 	\ZRUVWRXRXZZ[[[[[[[[	\ ?LLNN
 
    	
  Y Y Y

.c!ff..///!QQ!Q!QRSSUXXXXXXXXYsv   'K/ BK/ <%K/ "!K/ !K/ &AK/ -AK/ 4A4K/ )A)J K/ 
KK<K/ K(K/ /
M#9AMM#M#z/api/auth/loginc                     	 t          j                    } | st          ddi          dfS |                     dd                                          }|                     d          pd                                }|                     dd          }|r|st          ddi          dfS |st          dd	i          dfS t          |          st          dd
i          dfS t          j                            |          	                                }|st          ddi          dfS |
                    |          st          ddi          dfS t          j                     |j        t          d<   |j        t          d<   t          d|                                d          dfS # t           $ r<}t#          dt%          |                      t          ddi          dfcY d }~S d }~ww xY w)Nra   r   rc   rG   r   r   hcaptcha_tokenu0   이메일과 비밀번호를 입력해주세요.u#   hCaptcha 인증이 필요합니다.&   hCaptcha 인증에 실패했습니다.r   u;   이메일 또는 비밀번호가 올바르지 않습니다.  rd   re   u   로그인 성공rv   ry   u   로그인 오류: $   서버 오류가 발생했습니다.r{   )r   r   r   r(   r   r/   r
   rp   r   r   check_passwordr   r   rd   re   r   r)   r'   r*   )r    rG   r   r   rx   r-   s         r.   loginr     sH   ,O!! 	LG%DEFFKK"%%++--HHZ((.B5577"2B77 	_H 	_G%WXYY[^^^  	RG%JKLLcQQ~.. 	UG%MNOOQTTT z##%#006688 	jG%bcddfiii ""8,, 	jG%bcddfiii 	 "\	"m
)LLNN
 
    	
  O O O+3q66++,,,!GHII3NNNNNNNOsC   'F% A=F% (F% =!F% AF% &'F% AF% %
G+/1G& G+&G+z/api/auth/logoutc                     	 t          j                     dt           _        t          t	          ddi          d          } t
          j                            dd          }|                     |dddd	d dd
d	  	         |                     |ddddd dd
d	  	         | S # t          $ r}	 t          j                     t          t	          ddi          d          } t
          j                            dd          }|                     |dddd	d dd
d	  	         | cY d }~S #  t	          ddi          dfcY cY d }~S xY wd }~ww xY w)NFrw   u   로그아웃 되었습니다.ry   SESSION_COOKIE_NAMEr   r   r   /TLax)expiresmax_agepathdomainsecurehttponlysamesitez/apira   r   r{   )
r   r   r   r   r   r   rV   r(   
set_cookier)   )r   session_cookie_namer-   s      r.   logoutr   3  s   0S! !)5T)U!V!VX[\\ *0445JIVV 	 	 
	
 
	
 
	
 	 	 
	
 
	
 
	
  	S 	S 	S	SMOOO$Wg7]-^%_%_adeeH"-"4"8"89NPY"Z"Z 3RATW`dmr  ~B  MR  S  S  SOOOOOO	SG%KLMMsRRRRRRRRR	Ss7   BB 
E)A1D E D<5D?6E<D??Ez/api/auth/mec                  b   	 t          j        d          } | st          ddi          dfS t          |           }|s&t          j                     t          ddi          dfS t          d|                                i          dfS # t          $ r}t          dd	i          d
fcY d }~S d }~ww xY w)Nrd   ra   u   로그인이 필요합니다.r   u%   사용자를 찾을 수 없습니다.  rx   ry   r   r{   )r   r(   r   r   r   r   r)   rd   rx   r-   s      r.   get_current_userr  g  s    O+i(( 	LG%DEFFKK(11 	TMOOOG%LMNNPSSS/00#55 O O O!GHII3NNNNNNNOs(   (B 6B "$B 
B.B)#B.)B.z/api/auth/checkc                     	 t          j        d          } | r7t          |           }|r&t          d|                                d          dfS t          ddi          dfS # t
          $ r}t          ddi          d	fcY d }~S d }~ww xY w)
Nrd   T)authenticatedrx   ry   r  Fra   r   r{   )r   r(   r   r   r   r)   r  s      r.   
check_authr  x  s    
O+i(( 	U,W55D Ut||~~NNOOQTTT/00#55 O O O!GHII3NNNNNNNOs$   AA" A" "
B	,B>B	B	z/api/auth/find-usernamec                     	 t          j                    } | st          ddi          dfS |                     dd                                          }|st          ddi          dfS t          |          st          ddi          dfS t          j                            |          	                                }|st          dd	i          d
fS t          |j                  dk    r*|j        dd         dt          |j                  dz
  z  z   n|j        }t          d|j        |d          dfS # t          $ r<}t          dt          |                      t          ddi          dfcY d}~S d}~ww xY w)u'   이메일을 통한 사용자명 찾기ra   r   rc   rG   r       이메일을 입력해주세요.r   r   u@   해당 이메일로 가입된 계정을 찾을 수 없습니다.r     N*u    사용자명을 찾았습니다.)rw   re   masked_usernamery   u   아이디 찾기 오류: r   r{   )r   r   r   r(   r   r   r
   rp   r   r   r   re   r)   r'   r*   )r    rG   rx   r  r-   s        r.   find_usernamer    s   O!! 	LG%DEFFKK"%%++--  	OG%GHII3NNe$$ 	ZG%RSTTVYYY z##%#006688 	oG%ghiiknnn QTTXTaPbPbefPfPf$-+cS5G5G!5K.LLLlply9.
 
   	 	  O O O2#a&&22333!GHII3NNNNNNNOs6   'D3 <D3 '!D3 	AD3 A"D3 3
E9=1E4.E94E9z/api/auth/reset-passwordc                  &   	 t          j                    } |                     d          }|                     d          }|st          ddi          dfS t          j                            |                                          }|st          ddi          dfS d	                    d
 t          d          D                       }|t          j                    t          d          z   ddt          |<   	 t          ||           t          ddi          dfS # t          $ r/}t!          d|            t          ddi          dfcY d}~S d}~ww xY w# t          $ r/}t!          d|            t          ddi          dfcY d}~S d}~ww xY w)u$   비밀번호 재설정 코드 전송rG   r   ra   u   이메일이 필요합니다.rc   r   @   해당 이메일로 등록된 계정을 찾을 수 없습니다.r  r   c                 P    g | ]#}t          t          j        d                     $S 
   r*   secrets	randbelow.0_s     r.   
<listcomp>z"reset_password.<locals>.<listcomp>  +    $R$R$RAS):2)>)>%?%?$R$R$Rr6      r  minutesr   )rg   r   attemptsrw   4   인증 코드가 이메일로 전송되었습니다.ry      이메일 전송 실패: uM   이메일 전송에 실패했습니다. 잠시 후 다시 시도해주세요.r{   Nu   비밀번호 재설정 오류: u?   비밀번호 재설정 처리 중 오류가 발생했습니다.)r   r   r(   r   r
   rp   r   r   rS   ranger   r   r   password_reset_codessend_reset_emailr)   r'   )r    rG   r   rx   verification_coder-   s         r.   reset_passwordr$    s   'j!!!!"233 	LG%DEFFKK z##%#006688 	oG%ghiiknnn GG$R$Rq$R$R$RSS &",..9R+@+@+@@'
 '
U#	|U$5666I']^__addd 	| 	| 	|1a11222G%tuvvx{{{{{{{{	|  j j j333444!bcddfiiiiiiiijsV   AE AE AE 8"D 
E%$E	E
E EE 
F!$FFFz /api/auth/reset-password/confirmc                  6   	 t          j                    } |                     d          }|                     d          }|                     d          }|                     d          }t          |||g          st	          ddi          dfS t
          j                            |                                          }|st	          dd	i          d
fS t                              |          }|st	          ddi          dfS t          j                    |d         k    rt          |= t	          ddi          dfS |d         dk    rt          |= t	          ddi          dfS |d         |k    r#|dxx         dz  cc<   t	          ddi          dfS t          |          |_        t          j                                         t          |= t	          ddi          dfS # t"          $ r/}t%          d|            t	          ddi          dfcY d}~S d}~ww xY w)u5   비밀번호 재설정 확인 및 비밀번호 변경rG   r#  new_passwordr   ra   u>   이메일, 인증 코드, 새 비밀번호가 필요합니다.rc   r   r  r  >   인증 코드가 만료되었거나 존재하지 않습니다.r   '   인증 코드가 만료되었습니다.r     ua   인증 코드 시도 횟수를 초과했습니다. 새로운 인증 코드를 요청해주세요.rg      +   인증 코드가 올바르지 않습니다.rw   u6   비밀번호가 성공적으로 변경되었습니다.ry   u&   비밀번호 재설정 확인 오류: u<   비밀번호 변경 처리 중 오류가 발생했습니다.r{   N)r   r   r(   allr   r
   rp   r   r   r!  r   r   r   password_hashr	   r   r   r)   r'   )r    rG   r#  r&  r   rx   
reset_datar-   s           r.   confirm_reset_passwordr/    s   4g!!!! HH%899xx//"233E,l;<< 	mG%efggilll z##%#006688 	oG%ghiiknnn *--e44
 	mG%efggilll <>>J|444$U+G%NOPPRUUU j!Q&&$U+G  &I  J  K  K  MP  P  P f!222z"""a'"""G%RSTTVYYY 4LAA

 !'	#[\]]_bbb g g g:q::;;;!_`aacffffffffgsD   BG AG .G 7G <&G #.G AG 
H)$HHHc                    t          j        dd          }t          t          j        dd                    }t          j        d          }t          j        d          }t          ||g          st	          d           dS d	}d
| d}t                      }||d<   | |d<   ||d<   |                    t          |dd                     	 t          j	        ||          }	|	
                                 |	                    ||           |	                    |           |	                                 t	          d|             dS # t          $ r}
t	          d|
             d}
~
ww xY w)u'   비밀번호 재설정 이메일 전송SMTP_SERVERsmtp.gmail.com	SMTP_PORT587SMTP_USERNAMESMTP_PASSWORDP   SMTP 설정이 완료되지 않았습니다. 환경변수를 확인해주세요.Nu   M-Link 비밀번호 재설정uo   
    안녕하세요,
    
    M-Link 비밀번호 재설정을 요청하셨습니다.
    
    인증 코드: u   
    
    이 코드는 10분 후에 만료됩니다.
    본인이 요청하지 않았다면 이 이메일을 무시하세요.
    
    감사합니다.
    M-Link 팀
    FromToSubjectplainutf-8u0   비밀번호 재설정 이메일 전송 완료: r  r$   r%   r   r,  r'   r   attachr   smtplibSMTPstarttlsr   send_messagequitr)   rG   r#  smtp_server	smtp_portsmtp_usernamesmtp_passwordsubjectbodymsgserverr-   s              r.   r"  r"    s    )M+;<<KBIk51122IIo..MIo..M}-.. `aaa .G
 &  D //CCKCIC	NJJxgw//000	k955]M222C   HHHIIIII   -!--...s   A:E 
E*E%%E*c                    t          j        dd          }t          t          j        dd                    }t          j        d          }t          j        d          }t          ||g          st	          d           dS d	}d
| d}t                      }||d<   | |d<   ||d<   |                    t          |dd                     	 t          j	        ||          }	|	
                                 |	                    ||           |	                    |           |	                                 t	          d|             dS # t          $ r}
t	          d|
            Y d}
~
dS d}
~
ww xY w)   이메일 인증 코드 전송r1  r2  r3  r4  r5  r6  r7  Fu   M-Link 이메일 인증uw   
    안녕하세요,
    
    M-Link 회원가입을 위한 이메일 인증 코드입니다.
    
    인증 코드: ub   
    
    이 코드는 5분 후에 만료됩니다.
    
    감사합니다.
    M-Link 팀
    r8  r9  r:  r;  r<  u'   이메일 인증 코드 전송 완료: Tr  Nr=  rD  s              r.   send_verification_emailrO  A  s    )M+;<<KBIk51122IIo..MIo..M}-.. `aaau (G
 &  D //CCKCIC	NJJxgw//000
k955]M222C   ???@@@t   -!--...uuuuus   A:E 
E/E**E/z/api/auth/send-verificationc                     	 t          j                    } | st          ddi          dfS |                     dd                                          }|                     dd                                          }|                     dd                                          }|                     dd                                          }|st          dd	i          dfS t          |          st          dd
i          dfS |st          ddi          dfS |st          ddi          dfS t          |          st          ddi          dfS |st          ddi          dfS t          |          st          ddi          dfS t          j	        
                    |                                          }|rt          ddi          dfS t          j	        
                    |                                          }|rt          ddi          dfS d                    d t          d          D                       }|||t          j                    t!          d          z   dt"          |<   t%          ||          rt          ddi          dfS t          ddi          dfS # t&          $ r<}t)          dt+          |                      t          ddi          dfcY d }~S d }~ww xY w)!rN  ra   r   rc   rG   r   re   r   r   r  r   u#   사용자명을 입력해주세요.u#   비밀번호를 입력해주세요.ub   비밀번호는 최소 8자 이상이어야 하며, 영문자와 숫자를 포함해야 합니다.u&   hCaptcha 인증을 완료해주세요.r   r   u+   이미 가입된 이메일 주소입니다.r   r   c                 P    g | ]#}t          t          j        d                     $S r  r  r  s     r.   r  z%send_verification.<locals>.<listcomp>  r  r6   r  r)  r  )rg   re   r   r   rw   r  ry   u+   인증 코드 전송에 실패했습니다.r{   u   인증 코드 전송 오류: r   N)r   r   r   r(   r   r   r   r/   r
   rp   r   r   rS   r   r   r   r   email_verification_codesrO  r)   r'   r*   )	r    rG   re   r   r   r   existing_usernamer#  r-   s	            r.   send_verificationrT  q  sy   =O!! 	LG%DEFFKK"%%++--88J++113388J++1133"2B77==??  	OG%GHII3NNe$$ 	ZG%RSTTVYYY 	RG%JKLLcQQ 	RG%JKLLcQQ ** 	QG  &J  K  L  L  NQ  Q  Q 	UG%MNOOQTTT~.. 	UG%MNOOQTTT 
,,5,99??AA 	ZG%RSTTVYYY J00(0CCIIKK 	ZG%RSTTVYYY GG$R$Rq$R$R$RSS &  ",..9Q+?+?+??	+
 +
 ' #5*;<< 	ZI']^__adddG%RSTTVYYY O O O6c!ff66777!GHII3NNNNNNNOsb   'J% B4J% !J% J% J% +!J% J% "!J% AJ% AJ% A?J% J% %
K+/1K& K+&K+z/api/auth/verify-emailc            	         	 t          j                    } | st          ddi          dfS |                     dd                                          }|                     dd                                          }|st          ddi          dfS |st          ddi          dfS |t
          vrt          dd	i          dfS t
          |         }t          j                    |d
         k    rt
          |= t          ddi          dfS |d         |k    rt          ddi          dfS t          ||d                   }t          ||d         |t          |d                             }t          j                            |           t          j                                         	 ddlm}  ||j                  }|                    d          rt%          d|j         d           n%t%          d|                    d                      n6# t&          $ r)}t%          dt)          |                      Y d}~nd}~ww xY wt
          |= |j        t          d<   |j        t          d<   t          d|                                d          dfS # t&          $ r<}t%          dt)          |                      t          ddi          dfcY d}~S d}~ww xY w) u6   이메일 인증 코드 확인 및 회원가입 완료ra   r   rc   rG   r   r#  r  u$   인증 코드를 입력해주세요.r'  r   r(  rg   r+  re   r   )rd   re   rG   r-  r   r   r!   r   r   r   r   Nrd   r   rv   ry   u   이메일 인증 오류: r   r{   )r   r   r   r(   r   rR  r   r   r   r
   r   r	   r   r   r   r   r   rd   r'   r)   r*   re   r   )	r    rG   r#  stored_datar   rx   r   r   r-   s	            r.   verify_emailrW    sh   EO!! 	LG%DEFFKK"%%++-- HH%8"==CCEE  	OG%GHII3NN  	SG%KLMMsRR 000G%efggilll.u5 <>>K555(/G%NOPPRUUU v"333G%RSTTVYYY 1J8OPP ,0Z1HII	
 
 
 	
t

	\AAAAAA++DL99L	** flQUQ]lllmmmmdIYIYZaIbIbddeee 	\ 	\ 	\ZRUVWRXRXZZ[[[[[[[[	\
 %U+ "\	"m
?LLNN
 
    	
  O O O2#a&&22333!GHII3NNNNNNNOso   'J A$J J $J  AJ J $A?J $A)H J 
IH<7J <IAJ 
K1KKKz/api/auth/verify-userc                  t   	 t          j                    } | st          ddi          dfS |                     dd                                          }|st          ddi          dfS d}t          |          r3t          j                            |          	                                }n2t          j                            |	          	                                }|st          dd
i          dfS t          d|j
        |j        dd         dt          |j                            d          d                   dz
  z  z   dz   |j                            d          d         z   d          dfS # t          $ r<}t          dt!          |                      t          ddi          dfcY d}~S d}~ww xY w)u   사용자 존재 여부 확인ra   r   rc   
identifierr   u4   사용자명 또는 이메일을 입력해주세요.Nr   r   u=   해당 정보로 가입된 계정을 찾을 수 없습니다.r  u   사용자를 찾았습니다.r   r
  @r   r*  )rw   re   rG   ry   u   사용자 확인 오류: r   r{   )r   r   r   r(   r   r   r
   rp   r   r   re   rG   r   splitr)   r'   r*   )r    rY  rx   r-   s       r.   verify_userr\    s   O!! 	LG%DEFFKKXXlB//5577
  	cG%[\]]_bbb *%% 	E:''j'99??AADD:'''<<BBDDD 	lG%deffhkkk6Z^cS1A1A#1F1Fq1I-J-JQ-N&OORUUX\XbXhXhilXmXmnoXpp
 
   	 	  O O O2#a&&22333!GHII3NNNNNNNOs0   'E1 <E1 'B
E1 2A>E1 1
F7;1F2,F72F7)Ir   r   r   r   r   r   r   r   r	   r
   src.models.subscriptionr   r   r   r"   r&   r$   r   r   r   r  r?  email.mime.textr   email.mime.multipartr   werkzeug.securityr   r   base64urllib.parser   r   src.config.env_loaderr   src.utils.user_refr   r   r   r   __name__auth_bpr!  rR  r/   r5   r%   rO   rW   r]   routerq   setr   r   r   r   r   r   r   r   r   r   r  r  r  r$  r/  r"  rO  rT  rW  r\  r\   r6   r.   <module>ri     s   R R R R R R R R R R R R R R R R $ $ $ $ $ $ $ $ L L L L L L L L L L   				 ( ( ( ( ( ( ( ( 				   $ $ $ $ $ $ . . . . . . 4 4 4 4 4 4   ) ) ) ) ) ) ) ) % % % % % %            )FH
%
%      $# # # RY011"#899!	"6==??8f8f8fgg=:<  RY011"#899!	"6==??8f8f8fgg>;>  RY122"#9::!	"7MMOO9h9h9hiiB:H9% % <  &           	1E7CC(+ (+ DC(+X #%%4ufoNNL6 L6 ONL6\? ? ?B  4d d dL0 0 0
   	#fX66=Y =Y 76=Y~ 	 6(33-O -O 43-O^ 	!F8441S 1S 541Sf 	~w//O O 0/O  	 5'22O O 32O 	(6(;;!O !O <;!OF 	)F8<<)j )j =<)jV 	1F8DD6g 6g ED6gp. . .`. . .` 	,vh???O ?O @??OB 	'&::GO GO ;:GOR 	&99 O  O :9 O  O  Or6   