
    R7_i                         S SK JrJrJrJrJrJrJr  S SKJ	r	  SSK
Jr  S SKJrJrJr  S SKJr  S SKJrJrJrJrJrJrJr  S SKJr  S=S	 jrS>S jr\R<                  " S5      \S 5       5       r\R<                  " S5      \S 5       5       r \R<                  " S5      \S 5       5       r!\R<                  " S5      \S 5       5       r"\R<                  " S5      \S 5       5       r#\R<                  " S5      \S 5       5       r$\R<                  " SS/S9\S 5       5       r%\R<                  " SS/S9\S 5       5       r&\R<                  " SS/S9\S 5       5       r'\R<                  " SS /S9\S! 5       5       r(\R<                  " S"5      \S# 5       5       r)\R<                  " S$5      \\" S
5      S% 5       5       5       r*\R<                  " S&5      \\" S'5      S( 5       5       5       r+\R<                  " S)5      \S* 5       5       r,\R<                  " S+S/S9\S, 5       5       r-\R<                  " S+S/S9\S- 5       5       r.\R<                  " S.S /S9\S/ 5       5       r/\R<                  " S0S/S9\S1 5       5       r0\R<                  " S2S/S9\S3 5       5       r1\R<                  " S4S/S9\S5 5       5       r2\R<                  " S6S/S9\S7 5       5       r3\R<                  " S8S/S9\S9 5       5       r4\R<                  " S:S /S9\S; 5       5       r5g<)?    )render_templateredirecturl_forflashrequestjsonifygwraps   )admin_bp)admin_requiredlogin_requiredsuperadmin_required)AuthService)dbUserChallengeRecordDeploymentRecordCategoryConfigCategoryAdminRole)generate_password_hashc                    U c  U$ [        U [        5      (       a  U $ [        U [        [        45      (       a  [        U 5      $ [        U [        5      (       a,  U R                  5       R                  5       nUS;   a  gUS;   a  g[        U 5      $ )u   
将值转换为布尔值

处理以下情况：
- True/False -> 直接返回
- 'true'/'True'/'TRUE' -> True
- 'false'/'False'/'FALSE' -> False
- 1/0 -> True/False
- None -> 返回 default
)true1yesonT)false0nooff F)
isinstanceboolintfloatstrlowerstrip)valuedefaultvalue_lowers      5/Users/yu22x/Desktop/ge/ctf/app/routes/admin/views.pyto_boolr/   
   s~     }%%#u&&E{%kkm))+44;;;    viewerc                    ^  U 4S jnU$ )u   
方向访问权限装饰器 - 用于视图层

权限级别:
- viewer: 只读权限
- editor: 编辑权限
- owner: 管理权限
c                 4   >^  [        T 5      U U4S j5       nU$ )Nc                 ~  > [         R                  nU(       d   [        SS5        [        [	        S5      5      $ UR
                  [        R                  :X  a  T	" U /UQ70 UD6$ [        R                  R                  U UR                  S9R                  5       nU(       d   [        SS5        [        [	        S5      5      $ SS	S
S.nUR                  UR
                  S5      nUR                  T
S5      nXg:  a:  SSSS.n[        SUR                  T
T
5       S3S5        [        [	        S5      5      $ T	" U /UQ70 UD6$ )Nu   请先登录warningz
auth.logincategory_iduser_idu!   您没有该方向的访问权限dangeradmin.categoriesr         )r1   editorownerr   u   查看u   编辑u   管理u   需要   权限)r	   userr   r   r   roler   ADMINr   query	filter_byidfirstget)r7   argskwargsr@   admin_recordrole_levels
user_levelrequired_level
role_namesfmin_roles            r.   decorated_functionGcategory_access_required.<locals>.decorator.<locals>.decorated_function.   s/   66Dni0 566 yyDJJ&6t6v66 )..88' 9  eg 
  98D(: ;<< &'!a@K$):):A>J(__Xq9N*(0HxX
z~~hAB&I8T(: ;<<[242622r0   r
   )rO   rQ   rP   s   ` r.   	decorator+category_access_required.<locals>.decorator-   s!    	q	3 
	3> "!r0    )rP   rS   s   ` r.   category_access_requiredrV   $   s    !"D r0   /c                  T   [         R                  R                  [        R                  :H  n / nU (       a<  [
        R                  R                  [
        R                  5      R                  5       nO.[        R                  " [         R                  R                  5      n[        SUU S9$ )u   管理员首页zpages/admin/index.html)
categoriesis_superadmin)r	   r@   rA   r   rB   r   rC   order_bynameallr   get_user_categoriesrE   r   )rZ   rY   s     r.   indexr_   Q   sy     FFKK4::-M J#))22>3F3FGKKM
 #66qvvyyA
3$.'46 6r0   z	/settingsc                  T    SSK n [        SU R                  R                  5       S   S9$ )u8   系统设置页面（合并了AI配置和系统工具）r   Nzpages/admin/settings.html)python_version)sysr   versionsplit)rb   s    r.   settingsre   c   s(     6s{{GXGXGZ[\G]^^r0   z/datac                  j   [         R                  R                  SS5      n [         R                  R                  SS[        S9n[         R                  R                  SS[        S9n[         R                  R                  SS5      n[         R                  R                  S	S[        S9nS
n[        R
                  R                  [        R                  R                  5       5      R                  XSS9n[        R
                  nU(       a  US:w  a  UR                  US9nUR                  [        R                  R                  5       5      R                  X%SS9n SSKJn	  U	R                  " 5       n
U
 Vs0 s H&  oR                  UR                   UR"                  S._M(     nn0 n[        R
                  R%                  5       US'   UR'                  5        H0  n[        R
                  R                  US9R%                  5       X'   M2     [(        R
                  R                  [(        R                  R                  5       5      R                  XESS9n/ n SSKJn	  U	R
                  R                  U	R                   5      R+                  5       n
U
 Vs/ s H  nUR                  UR                   S.PM     nn[-        SU UR.                  UUR.                  UUUUUR.                  UU[0        R2                  R4                  [6        R8                  :H  S9$ s  snf !   0 n GN}= fs  snf !   / n Nv= f)u9   数据管理页面 - 合并用户、题目、部署管理tabusers
users_pager   )typechallenges_pagechallenges_categoryr]   deployments_page   F)pageper_page	error_out)challenge_typer   )r   )r\   icon)rE   r\   zpages/admin/data.html)
active_tabrh   users_pagination
challengeschallenges_paginationrl   categories_dictchallenge_countsdeploymentsdeployments_paginationcategories_listrZ   )r   rH   rG   r&   r   rC   r[   
created_atdescpaginater   rD   app.models.database.modelsr   get_all_categoriesrE   r\   rs   countkeysr   r]   r   itemsr	   r@   rA   r   rB   )rt   ri   rk   rl   rm   rp   ru   challenges_queryrw   r   all_categoriescatrx   ry   cat_idr{   r|   cs                     r.   datar   l   s    !!%1J!!,!<Jll&&'8!#&FO!,,**+@%H||''(:AC'HH zz**4??+?+?+ABKKe L 
 ',,2e;+55EX5Y,55o6P6P6U6U6WXaa5 b 
='::<SabSaC66CHHchh#GGSab
 -3399;U!&&(#2#8#8#B#BRX#B#Y#_#_#a  ) .33<<=M=X=X=]=]=_`iiE j 
 O='--66~7J7JKOOQAOPA!$$7P 2$./55*:$9$?$?/D-@)8*:%;%A%A0F)8'(vv{{djj'@B B1 c$ Qs<   L 8-L%L =L, #L':L, L L$'L, ,L2z/usersc                  (    [        [        SSS95      $ )u-   用户管理页面 - 重定向到数据管理
admin.datarh   rg   r   r   rU   r0   r.   rh   rh           GLg677r0   z/challengesc                  (    [        [        SSS95      $ )u-   题目管理页面 - 重定向到数据管理r   rv   r   r   rU   r0   r.   rv   rv      s     GLl;<<r0   z/deploymentsc                  (    [        [        SSS95      $ )u-   部署管理页面 - 重定向到数据管理r   rz   r   r   rU   r0   r.   rz   rz      s     GLm<==r0   z/api/user/<int:user_id>GET)methodsc           
          [         R                  R                  U 5      nU(       d  [        SSS.5      S4$ [        R                  R                  U S9R                  5       n[        R                  R                  U S9R                  5       nUR                  UR                  UR                  UR                  UR                  UR                  (       a  UR                  R                  S5      OSUR                  (       a  UR                  R                  S5      OSUUS.	n[        S	US
.5      $ ! [          a&  n[        SS[#        U5       3S.5      S4s SnA$ SnAff = f)u   获取用户详情F   用户不存在successmessage  r8   z%Y-%m-%d %H:%MN)	rE   usernameemailrA   	is_activer}   
last_loginchallenge_countdeployment_countT)r   r   u   错误:   )r   rC   rG   r   r   rD   r   r   rE   r   r   rA   r   r}   strftimer   	Exceptionr(   )r8   r@   r   r   	user_dataes         r.   api_get_userr      s(   Pzz~~g&u9JKLcQQ *//99'9JPPR+11;;G;LRRT ''ZZIIHL$//223CD]aHL$//223CD]a. 0

	 4;<< P5xAx5HIJCOOPs#   5D2 C9D2 2
E"<EE"E"POSTc                     [         R                  R                  U 5      nU(       d  [        SSS.5      S4$ [        R
                  " 5       nSU;   ai  US   (       a_  [         R                  R                  US   S9R                  5       nU(       a   UR                  U :w  a  [        SSS.5      S4$ US   Ul	        S	U;   a  US	   S
;   a
  US	   Ul
        SU;   a  [        US   SS9Ul        SU;   a  US   (       a  [        US   SS9Ul        [        R                   R#                  5         [        SSS.5      $ ! [$         aD  n[        R                   R'                  5         [        SS[)        U5       3S.5      S4s SnA$ SnAff = f)u   更新用户信息Fr   r   r   r   r   u   该邮箱已被使用  rA   )r@   	moderatoradminr   Tr,   passwordpbkdf2:sha256methodu   用户信息更新成功u   更新失败: r   N)r   rC   rG   r   r   get_jsonrD   rF   rE   r   rA   r/   r   r   password_hashr   sessioncommitr   rollbackr(   )r8   r@   r   existing_userr   s        r.   api_update_userr      sm    Vzz~~g&u9JKLcQQ! d?tG} JJ00tG}0EKKMM!1!1W!<5=TUVX[[[gDJ T>d6l.LLVDI $$T+%6EDN $z"2!7Z8HQ`!aD


44NOPP V


5~c!fX5NOPRUUUVs*   5D; A9D; 2BD; ;
F	9F>F	F	z/api/user/createc            	          [         R                  " 5       n U R                  S5      (       d  [        SSS.5      S4$ U R                  S5      (       d  [        SSS.5      S4$ U R                  S5      (       d  [        SS	S.5      S4$ [        R
                  R                  U S   S
9R                  5       (       a  [        SSS.5      S4$ [        R
                  R                  U S   S9R                  5       (       a  [        SSS.5      S4$ [        U R                  S5      SS9n[	        U S   U S   [        U S   SS9U R                  SS5      US9n[        R                  R                  U5        [        R                  R                  5         [        SSUR                  S.5      $ ! [         aD  n[        R                  R!                  5         [        SS[#        U5       3S.5      S4s SnA$ SnAff = f)u   创建新用户r   Fu   用户名不能为空r   r   r   u   邮箱不能为空r   u   密码不能为空)r   u   用户名已存在r   u   邮箱已被使用r   Tr   r   r   rA   r@   )r   r   r   rA   r   u   用户创建成功)r   r   r8   u   创建失败: r   N)r   r   rG   r   r   rC   rD   rF   r/   r   r   r   addr   rE   r   r   r(   )r   r   new_userr   s       r.   api_create_userr     s   %V! xx
##u9PQRTWWWxx  u9MNOQTTTxx
##u9MNOQTTT ::j)9:@@BBu9MNOQTTT ::d7m4::<<u9MNOQTTT DHH[14@	*%w-0j1A/Z&&)
 	

x 


44HU]U`U`abb V


5~c!fX5NOPRUUUVs=   :F, %F, #%F, 	AF, AF, BF, ,
G:69G5/G:5G:DELETEc                 v    [         R                  R                  U 5      nU(       d  [        SSS.5      S4$ UR                  [
        R                  :X  a  [        SSS.5      S4$ [        R                  R                  U S9R                  5         [        R                  R                  U5        [        R                  R                  5         [        SS	UR                   S
3S.5      $ ! [         aD  n[        R                  R                  5         [        SS[!        U5       3S.5      S4s SnA$ SnAff = f)u*   删除用户 - 仅超级管理员可操作Fr   r   r   u   不能删除超级管理员i  r   Tu   用户 u
    已删除   删除失败: r   N)r   rC   rG   r   rA   r   rB   r   rD   deleter   r   r   r   r   r   r(   )r8   r@   r   s      r.   api_delete_userr   1  s   Vzz~~g&u9JKLcQQ 99

"u9VWXZ]]] 	%%g%6==? 	

$


4gdmm_J4WXYY V


5~c!fX5NOPRUUUVs)   5C* -C* &BC* *
D849D3-D83D8z/categoriesc                      [         R                  =(       a+    [         R                  R                  [        R                  :H  n [        SU S9$ )u   方向管理页面zpages/admin/categories.htmlis_admin)r	   r@   rA   r   rB   r   r   s    r.   rY   rY   M  s1    
 vv3!&&++3H88LLr0   z/categories/<category_id>c                 N  ^^	 [         R                  R                  U 5      nU(       d   [        SS5        [	        [        S5      5      $ Sn[        R                  R                  [        R                  :w  aY  [        R                  R                  U [        R                  R                  S9R                  5       nU(       a  UR                  OSnUR                  SS9nS	S
KnS	S
Km	SUU	4S jjmT" U5      nUR%                  USSS9nUR'                  SS5      n[)        SUUUS9$ )u   方向详情配置页面   方向不存在r9   r:   r>   r6   r1   Tinclude_configr   Nc                 X  >^ [        U [        5      (       a;  U R                  5        VVs0 s H  u  p#UT" UT(       a  T SU 3OU5      _M     snn$ [        U [        5      (       a:  [	        U 5       VVs/ s H!  u  pET" UT(       a  T SU S3OSU S35      PM#     snn$ [        U [
        5      (       ag  [        U4S jS 5       5      nU(       a  T	R                  SSU 5      nU$ T	R                  SS	U 5      nT	R                  S
S	U5      nUR                  5       $ U $ s  snnf s  snnf )u   清理对象中的控制字符

Args:
    obj: 要清理的对象
    path: 当前字段路径（用于识别 prompt 相关字段）
.[]c              3   H   >#    U  H  oTR                  5       ;   v   M     g 7f)N)r)   ).0keywordpaths     r.   	<genexpr>:category_detail.<locals>.clean_for_json.<locals>.<genexpr>~  s$      " JgTZZ\"9 Js   ")promptcontentdescriptioninstructionscriptz [\x00-\x08\x0B\x0C\x0E-\x1F\x7F]r#   z[\x00-\x1F\x7F] z +)	r$   dictr   list	enumerater(   anysubr*   )
objr   kviitemis_prompt_fieldcleanedclean_for_jsonres
    `      r.   r   'category_detail.<locals>.clean_for_jsonp  s$    c4  SVS\S\S^_S^41A~a$D61#AFFS^__T""^ghk^lm^lSZSTN44D61#Qq1XN^lmmS!! " " J " O  &&!Db#N &&!3S#>&&W5}}&J7 `ms   $D 6(D&F),:)ensure_ascii
separatorsz	</script>z
<\/script>z pages/admin/category_detail.html)categorycategory_jsonuser_permission)r#   )r   rC   rG   r   r   r   r	   r@   rA   r   rB   r   rD   rE   rF   to_dictjsonr   dumpsreplacer   )
r7   r   	user_rolerJ   category_datajson_libcategory_data_cleanedcategory_json_strr   r   s
           @@r.   category_detailr   V  s   
 ##''4H* 2344 Ivv{{djj $**44#FFII 5 
 %' 	 *6L%%8	 $$D$9M # #J +=9 '<5]gh)11+}M=#8(9*35 5r0   z'/categories/<category_id>/form-designerr=   c                     [         R                  R                  U 5      nU(       d   [        SS5        [	        [        S5      5      $ UR                  SS9n[        SUUR                  S/ 5      S9$ )	u   表单设计器页面r   r9   r:   Tr   zpages/admin/form_designer.htmlform_fields)r   r   )r   rC   rG   r   r   r   r   r   )r7   r   category_dicts      r.   form_designerr     sq    
 ##''4H* 2344$$D$9M;#0&3&7&7r&JL Lr0   z/user-permissionsc                  (    [        [        SSS95      $ )uH   用户权限管理页面 - 重定向到数据管理页面的用户标签r   rh   r   r   rU   r0   r.   user_permissionsr     r   r0   z#/api/user/<int:user_id>/permissionsc           	          [         R                  R                  U 5      nU(       d  [        SSS.5      S4$ [        R                  R                  U S9R                  5       n[        SUR                  UR                  UR                  UR                  S.U Vs/ s H  o3R                  5       PM     snS.5      $ s  snf ! [         a#  n[        S[        U5      S.5      S	4s S
nA$ S
nAff = f)u   获取用户的方向权限Fr   r   errorr   r   T)rE   r   r   rA   )r   r@   permissionsr   N)r   rC   rG   r   r   rD   r]   rE   r   r   rA   r   r   r(   )r8   r@   r  pr   s        r.   api_get_user_permissionsr    s    Azz~~g&u7HIJCOO $))33G3DHHJgg MM			 2==AIIK=	
 	 		 > A53q6:;S@@As5   5C A#C B=4C =C 
C/C*$C/*C/c           
      r    [         R                  R                  U 5      nU(       d  [        SSS.5      S4$ [        R
                  " 5       nUR                  S5      nUR                  SS5      nU(       d  [        SSS.5      S	4$ [        R                  R                  U5      nU(       d  [        SS
S.5      S4$ [        R                  R                  U US9R                  5       nU(       a  XFl
        O*[        U UUS9n[        R                  R                  U5        [        R                  R                  5         [        SSUR                   SUR                    SU S3S.5      $ ! ["         aA  n[        R                  R%                  5         [        S['        U5      S.5      S4s SnA$ SnAff = f)u   设置用户的方向权限Fr   r   r   r7   rA   r=   u   方向ID不能为空r   r   r8   r7   r8   r7   rA   Tu
   已授予 u    对 u    的r?   r   r   N)r   rC   rG   r   r   r   r   r   rD   rF   rA   r   r   r   r   r   r\   r   r   r(   )	r8   r@   r   r7   rA   r   existingnew_permissionr   s	            r.   api_set_user_permissionr
    s   +Azz~~g&u7HIJCOO!hh}-xx)u7MNOQTTT "''++K8u7HIJCOO !&&00# 1 
 %' 	
  M +'N
 JJNN>*


#DMM?%d4&PVW
  	  A


53q6:;S@@As0   5E+ AE+ 5E+ =B-E+ +
F656F1+F61F6z1/api/user/<int:user_id>/permissions/<category_id>c                     [         R                  R                  U US9R                  5       nU(       d  [	        SSS.5      S4$ [
        R                  R                  U5        [
        R                  R                  5         [	        SSS.5      $ ! [         aA  n[
        R                  R                  5         [	        S[        U5      S.5      S	4s S
nA$ S
nAff = f)u   删除用户的方向权限r  Fu   权限记录不存在r   r   Tu   权限已删除r   r   N)r   rC   rD   rF   r   r   r   r   r   r   r   r(   )r8   r7   
permissionr   s       r.   api_delete_user_permissionr    s    A"((22# 3 
 %' 	
 u7NOPRUUU


*%


44EFGG A


53q6:;S@@As%   AB A
B 
C6CCCz)/api/user/<int:user_id>/permissions/batchc                     [         R                  R                  U 5      nU(       d  [        SSS.5      S4$ [        R
                  " 5       nUR                  S/ 5      n[        R                  R                  U S9R                  5         U HY  nUR                  S5      nUR                  SS	5      nU(       d  M/  [        U UUS
9n[        R                  R                  U5        M[     [        R                  R                  5         [        SSUR                   S3S.5      $ ! [         aA  n[        R                  R                  5         [        S[!        U5      S.5      S4s SnA$ SnAff = f)u   批量设置用户权限Fr   r   r   r  r   r7   rA   r=   r  Tu
   已更新 u    的权限配置r   r   N)r   rC   rG   r   r   r   r   rD   r   r   r   r   r   r   r   r   r(   )	r8   r@   r   r  permr7   rA   r	  r   s	            r.   api_batch_set_permissionsr    s<    Azz~~g&u7HIJCOO!hh}b1 	%%g%6==?  D((=1K88FH-D{!.# +"
 

~.   	

#DMM?2BC
  	  A


53q6:;S@@As*   5D# A?D# ;A'D# #
E.-6E)#E.)E.z/api/cleanup-deploymentsc                  Z    SSK J n Jn  SSKJn  U R	                  5       nX1" SS9-
  n[
        R                  R                  [        R                  " [
        R                  S:H  [        R                  " [
        R                  R                  S5      [
        R                  U:  5      [        R                  " [
        R                  U:  [
        R                  R                  SS	/5      5      5      5      R!                  5       nU" 5       nSnSnU H  n	 U	R                  S:X  ai  U	R"                  (       a2   UR%                  U	R&                  U	R"                  U	R(                  5        [        R0                  R3                  U	5        US-  nM}  U	R"                  (       a2   UR%                  U	R&                  U	R"                  U	R(                  5        SU	l
        US-  nM     [        R0                  R5                  5         Xx-   nSU S3nUS:  a  USU SU S3-  n[7        SUUUUS.5      $ ! [*         a.  n
[-        S
U	R&                   S[/        U
5       35         Sn
A
NSn
A
ff = f! [*         a.  n
[-        S
U	R&                   S[/        U
5       35         Sn
A
NSn
A
ff = f! [*         a0  n
[-        SU	R&                   S[/        U
5       35         Sn
A
GM  Sn
A
ff = f! [*         aA  n
[        R0                  R9                  5         [7        S[/        U
5      S.5      S4s Sn
A
$ Sn
A
ff = f)u   清理过期部署r   )datetime	timedelta)DockerExecutionService   )hoursexpiredNrunningstoppedu   清理部署 u	    失败: r   u   处理部署 u    时出错: 
   已清理 u    个过期部署u
   （删除 u    个，标记 u    个）T)r   r   deletedmarkedr   Fr   r   )r  r  .app.services.deployment.core.execution_servicer  utcnowr   rC   filterr   or_statusand_
expires_atisnotr}   in_r]   working_directorydelete_deploymentdeployment_uuidexternal_portr   printr(   r   r   r   r   r   )r  r  r  nowcutoffexpired_deploymentsdocker_servicedeleted_countmarked_count
deploymentr   total_countr   s                r.   api_cleanup_deploymentsr3  K  s   UA0Yooyr** /44;;FF ''94$//55d;$//#5
 $//&8$++//I0FG
 #% 	" 01-J!$$	1!33a*<< * : : * < < * 8 8 JJ%%j1!Q&M "33a*<< * : : * < < * 8 8 )2J% A%L? .H 	

#2{m+;<1M?.gVVG $"
  	?  ) a!M*2L2L1MYWZ[\W]V^"_``a  ) a!M*2L2L1MYWZ[\W]V^"_``a
  j&@&@%AcRSfXVW$  A


53q6:;S@@As   DK !J"71H,($J"K J" 1I'J"AK ,
I$6$IJ"I$$J"'
J1$JJ"JJ""
K,$KK KK 
L*)6L%L*%L*z/api/cleanup-invalid-challengesc                  "    SSK n [        R                  R                  5       nSnU Hf  nUR                  (       d  M  U R
                  R                  UR                  5      (       a  MB  [        R                  R                  U5        US-  nMh     [        R                  R                  5         [        SUSU S3S.5      $ ! [         aA  n[        R                  R                  5         [        S[        U5      S	.5      S
4s SnA$ SnAff = f)u   清理无效题目记录r   Nr   Tr  u    个无效题目记录)r   r   r   Fr   r   )osr   rC   r]   
output_dirr   existsr   r   r   r   r   r   r   r(   )r5  rv   r   	challenger   s        r.   api_cleanup_invalid_challengesr9    s    A %**..0
#I###BGGNN9;O;O,P,P

!!),
	 $ 	

#E7*@A
  	
  A


53q6:;S@@As)   8C (C *AC 
D6D	D	Dz/api/backup-databasec                      SSK n SSKnSSKnSSKJn  SSKJn  SSKJn  U" UR                  5      nUS-  S-  nUR                  SSS	9  UR                  5       R                  S
5      nUR                  S:X  Ga  U" UR                  5      n	U	R                  5       (       d  [        SSU	 3S.5      S4$ U	R!                  5       R"                  n
USU S3-  nSSKnUR'                  [)        U	5      5      nUR'                  [)        U5      5      nUR+                  U5        UR-                  5         UR-                  5         USU S3-  n[/        US5       nUR/                  US5       nUR1                  UU5        SSS5        SSS5        UR3                  5         UR!                  5       R"                  nSnUR                  5       R5                  5       US-  S-  S-  -
  nSnUR7                  S5       H8  nUR!                  5       R8                  U:  d  M#  UR3                  5         US-  nM:     [        SS[)        UR;                  U5      5      UU
US.5      $ UR                  S:X  Ga   SSKnSSKJ n  USU S 3-  n UR'                  URD                  URF                  URH                  URJ                  URL                  S!9nSSK'nU RP                  RS                  5       nURL                  US"'   S#S$URD                  S%[)        URF                  5      S&URJ                  S'URH                  S(S)S*[)        U5      /n URU                  UUSSSS+S,9nUR-                  5         USU SJ3-  n[/        US5       nUR/                  US5       nUR1                  UU5        SSS5        SSS5        UR3                  5         UR!                  5       R"                  nSnUR                  5       R5                  5       US-  S-  S-  -
  nSnUR7                  SK5       H8  nUR!                  5       R8                  U:  d  M#  UR3                  5         US-  nM:     [        SS[)        UR;                  U5      5      UUSL.5      $ [        SSMUR                   3S.5      S4$ ! , (       d  f       GN"= f! , (       d  f       GN,= f! [B         a    [        SSS.5      S4s $ f = f! URV                   a#    UR-                  5         [        SS-S.5      S4s $ URX                  [Z        4 Ga!  nUR-                  5         SS.K.J/nJ0n   U" URb                  5      n!U!R'                  5        n"SS/K.J2n#  U#" U!5      n$U$Rg                  5       n%[/        US0S1S29 n&U&Ri                  S35        U&Ri                  S4UR                  5       R                  S55       S635        U&Ri                  S7URH                   S835        U% GH  n'U&Ri                  S9U' S635        U&Ri                  S:U' S;35        U"Rk                  U " S<U' S=35      5      nURm                  5       n(U((       d  Mb  URo                  5       n)S>Rq                  U) V*s/ s H	  n*S=U* S=3PM     Os  sn*f sn*5      n+U( GH_  n,/ n-U, GH&  n.U.c  U-Rs                  S?5        M  [u        U.[(        5      (       a)  U.Rw                  S@SA5      n/U-Rs                  S@U/ S@35        MX  [u        U.[x        [z        45      (       a  U-Rs                  [)        U.5      5        M  [u        U.[|        5      (       a  U-Rs                  U.(       a  SBOSC5        M  [u        U.U5      (       a%  U-Rs                  S@U.R                  5        S@35        M  [)        U.5      Rw                  S@SA5      n0U-Rs                  S@U0 S@35        GM)     S>Rq                  U-5      n1U&Ri                  SDU' SEU+ SFU1 SG35        GMb     GM     SSS5        O! , (       d  f       O= fSSS5        O! , (       d  f       O= fU!R                  5          SnAGNSnAff = f! [         aD  nSH[        5       ;   a  WR-                  5         [        SSI[)        U5       3S.5      S4s SnA$ SnAff = f! , (       d  f       GN= f! , (       d  f       GN= f! [         a:  nSSKCn2U2R                  5         [        SSN[)        U5       3S.5      S4s SnA$ SnAff = f)Ou   备份数据库r   N)r  )Path)ConfigbackupsdatabaseT)parentsexist_okz%Y%m%d_%H%M%SsqliteFu   数据库文件不存在: r   r   ctf_z.dbz.db.gzrbwb   r  <   z*.gzr   u   数据库备份成功)r   r   backup_filebackup_sizedb_sizedeleted_old
postgresql)ISOLATION_LEVEL_AUTOCOMMITu;   未安装 psycopg2，请运行: pip install psycopg2-binaryr   z.sql)hostportr>  r@   r   
PGPASSWORDpg_dumpz-hz-pz-Uz-dz-Fr  z-fi,  )envcapture_outputtextchecktimeoutu   备份超时（超过5分钟）)create_enginerS  )inspectwzutf-8)encodingu   -- PostgreSQL 数据库备份
u   -- 备份时间: z%Y-%m-%d %H:%M:%S
u   -- 数据库: z

u	   
-- 表: zTRUNCATE TABLE "z" CASCADE;

zSELECT * FROM ""z, NULL'z''TRUEFALSEzINSERT INTO "z" (z
) VALUES (z);
connu   PostgreSQL 备份失败: z.sql.gzz*.sql.gz)r   r   rG  rH  rJ  u   不支持的数据库类型: u   备份失败: )Er5  shutilgzipr  pathlibr;  configr<  BASE_DIRmkdirr+  r   DATABASE_TYPEDB_PATHr7  r   statst_sizesqlite3connectr(   backupcloseopencopyfileobjunlink	timestampglobst_mtimerelative_topsycopg2psycopg2.extensionsrL  ImportErrorPOSTGRES_HOSTPOSTGRES_PORTPOSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORD
subprocessenvironcopyrunTimeoutExpiredCalledProcessErrorFileNotFoundError
sqlalchemyrV  rS  SQLALCHEMY_DATABASE_URIrW  get_table_nameswriteexecutefetchallr   joinappendr$   r   r&   r'   r%   	isoformatdisposer   locals	traceback	print_exc)3r5  ra  rb  r  r;  r<  project_root
backup_dirrr  db_pathrI  rG  rk  source_connbackup_conncompressed_filef_inf_outcompressed_size	keep_dayscutoff_timer/  
old_backuprv  rL  r`  r~  rQ  cmdresultr   rV  rS  engine
connectionrW  	inspectortablesrO   tablerowscolumnscol	col_namesrowvaluesvalval_escapedval_str
values_strr  s3                                                      r.   api_backup_databaser    s   f% ! FOO,!I-
:
5 LLN++O<	8+6>>*G>>##$9'C     lln,,G %i['<<K !//#g,7K!//#k*:;K{+ )T)F+CCOk4(DYY5&&tU3 6 )
   .224<<O I",,.224	B8Kb8PQKM(oof5
??$--;%%'!Q&M 6
 2"?#>#>|#LM.",   !!\1J %i['==Ki''----#//--#55 (  "jjoo'$*$<$<L! &..#f223&..&,,##k*F%'^^'+!" # , FN 

 )T)G+DDOk4(DYY5&&tU3 6 )
   .224<<O I",,.224	B8Kb8PQKM(ooj9
??$--;%%'!Q&M :
 2"?#>#>|#LM.,    89M9M8NO   c 65 )(B  $Z    V "00 JJL"#(!B$    #557HI 7%JJL ?*6+I+IJF)Z6$+FO	!*!:!:!<!+sWEGG$EFGG&78O8OPc8d7eeg$hiGGnV5G5G4H$MN *0 !*UG2(> ? !*;E7/(R S *4););D?SXRYYZA[<\)]'-'8#'4.4kkmG04		QX:YQX#Qse1:QX:Y0ZI/31336C/2{06f0E1;C1E1E>Akk#t>T06+a>P0Q1;C#u1N1N06c#h0G1;C1F1F06fQX0Y1;C1J1J06#--/ARRS>T0U:=c(:J:J3PT:U06'!n0M 47" 6:YYv5F
()-wc)T^_i^jjn0o(p) 04 *0 FEE *))^ NN$$o7%v  VX%JJL$8QA     65 )(@  %c!fX.
   	sp  B1b; 4B!b; R((R;R(Bb; Ab; b; ,
R: 6	b;  B;a <S a  b; 5b)bb)#Bb; 7Ab; 9b; 
R%	 R((
R72b; :Sb; Sb; 0a
a a":`>*`C_=_=,Y=<E8_=4	`=
``	`>
`%	!`>8a >aa 
b9b	b
b; bb; 
b&	!b))
b83b; ;
c?/c:4c?:c?z/api/reset-databasec                  D    [         R                  R                  5         [        R                  R                  5         [        R                  R                  [        R                  [        R                  :g  5      R                  5         [        R                  R                  5         [        R                  R                  5         [        SSS.5      $ ! [         aA  n [        R                  R                  5         [        S[!        U 5      S.5      S4s Sn A $ Sn A ff = f)u!   重置数据库（危险操作）Tu   数据库已重置r   Fr   r   N)r   rC   r   r   r   r  rA   r   rB   r   r   r   r   r   r   r   r(   )r   s    r.   api_reset_databaser    s    A$$& 	%%' 	

$))tzz1299; 	""$


+
  	  A


53q6:;S@@As   CC 
D6DDDz!/api/challenge/<int:challenge_id>c                      SSK Jn  U" U 5      nU(       a  [        SSS.5      $ [        SSS.5      S4$ ! [         a&  n[        SS	[	        U5       3S.5      S
4s SnA$ SnAff = f)u!   删除题目 - 管理员可操作r   )delete_challengeTu   题目删除成功r   Fu   题目不存在或删除失败r   r   r   N)app.models.database.operationsr  r   r   r(   )challenge_idr  r   r   s       r.   api_delete_challenger    ss    	VC"<0t8LMNNu9YZ[]``` V5~c!fX5NOPRUUUVs   "5 5 
A%A A% A%N)F)r1   )6flaskr   r   r   r   r   r   r	   	functoolsr   r#   r   app.services.auth.decoratorsr   r   r   app.services.authr   r   r   r   r   r   r   r   r   werkzeug.securityr   r/   rV   router_   re   r   rh   rv   rz   r   r   r   r   rY   r   r   r   r  r
  r  r  r3  r9  r  r  r  rU   r0   r.   <module>r     s   P P P   \ \ ) w w w 44+Z 
6  6  
_  _ 
>B  >B@ 
8  8 
=  = 
>   > 
)E7;P  <P6 
)F8<"V  ="VH 
"VH5'V  6'VT 
)H:>V  ?V4 
M  M 
+,(#D5 $  -D5N 
9:(#L $  ;L$ 
#$8  %8
 
5wGA  HA0 
5xH-A  I-A` 
ChZXA  YA( 
;fXN"A  O"AV 
*VH=WA  >WAt 
1F8DA  EA6 
&9h  :hV 
%x8A  9A2 
3hZHV  IVr0   