4},C ddlZddlZddlZddlZddlZddlmZmZddlm Z ddl m Z m Z m Z mZmZmZddlmZddlmZddlmZmZmZddlmZmZmZmZmZmZm Z dd l!m"Z"d d l#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)d d l*m+Z+d Z,dZ-Gdde Z.eGddZ/Gdde Z0eGddZ1de1fdZ2e.j3fde4de/dede.de e5e1ff dZ6de/dede e5e1ffdZ7de4de5fdZ8dAde e4de5fd!Z9de4de:fd"Z;dBd#e5d$ee.fd%ZdBd#e5de=fd'Z?de=fd(Z@de=fd)ZAd*ZBdBde/fd+ZC dAd,e/de/fd-ZD dBde4d.e4d/ee e/fd0e5fd1ZEd.e4de e4e4e4ffd2ZFde4d3ee.fd4ZGde4de:fd5ZHde4de:fd6ZIde4d7ee.fd8ZJde4fd9ZKde4fd:ZLd;e5d7ee.de=fd<ZMd;e5de=fd=ZNdAd;e5de=fd>ZOd?ZPd@ZQdS)CN) dataclassfield)Enum)OptionalTupleDictUnionIterableAny)_remount_cagefs)cpusers)CLWPOS_VAR_DIRCLWPOS_UIDS_PATHALLOWED_MODULES_JSON) uid_by_name acquire_lockget_server_wide_optionsServerWideOptionsExtendedJSONEncoder name_by_uidis_user_owned_by_reseller)Feature) ALL_SUITESAWPSuite PremiumSuiteCDNSuite CDNSuiteProOLD_NEW_SUITE_NAME_PAIRS)get_cached_visible_any_userzsuites_allowed.jsonceZdZdZdZdZdZdS)FeatureStatusEnumdefaultdisabledvisibleallowedN)__name__ __module__ __qualname__DEFAULTDISABLEDVISIBLEALLOWED*py/clwpos/feature_suites/configurations.pyr#r#3s(GHGGGGr0r#ceZdZUeed<eeefed<eeefed<e eed<eee j fed<e e Ze eeefed<dZed Zd S) AdminSuitesConfigversionsuites attributes unique_idpurchase_dates)default_factory whmcs_suitesct|jttD]}|j|dS)z} Remove unknown suites from resulting structure. Actual for downgrade cases, see AWP-272 for details N)setr5 differencerpop)selfsuites r1 __post_init__zAdminSuitesConfig.__post_init__KsR %%00ZAA # #E KOOE " " " " # #r0c ttt|jt|jz}|SN)sortedr<listr5keysr:)r? all_suitess r1 suites_listzAdminSuitesConfig.suites_listSsOCT[%5%5%7%7 8 84@Q@V@V@X@X;Y;Y YZZ[[ r0N)r(r)r*int__annotations__rstrr#r rdatetimedaterdictr:rApropertyrHr/r0r1r3r3As LLL '' ((((S#X}hm+,,,,;@5QU;V;V;VL(4%6 678VVV###Xr0r3ceZdZdZdZdZdS) StatusSourcer$manualbillingN)r(r)r*r+ COMMAND_LINEBILLING_OVERRIDEr/r0r1rQrQYs GL r0rQceZdZUeed<dS) FeatureStatusstatusN)r(r)r*r#rJr/r0r1rWrW_s r0rWreturncd|D}tjtjtjgt |fddS)z Choose final feature status according to priority CDN is included to multiple suites, so need to decide is it allowed/visible/etc e.g if at least one suite with cdn feature is allowed -> feature is allowed c$g|] }|r |j |SrCrX).0feature_statuss r1 z*_choose_feature_status..js6HHH. H%3%:%F%F%F%Fr0c8|jSrC)indexrX)itemstatus_prioritys r1z(_choose_feature_status..msO,A,A$+,N,Nr0)keyr)r#r.r-r,rD)target_statusessort_byrcs @r1_choose_feature_statusrhcs_HHOHHHG(02C2KM^MghO 'NNNN O O OPQ RRr0uid admin_configserver_wide_options allowed_statec 0 dtdtfd dtdtdtdtf fd }i}|jD]}t|jjv}|tjks|tjkr|rd}nd}|j |} |j |} tt||D]B} t| | |||| | |||| | g|| <C|S) ar Construct feature allowance dict based on given suites. We require both primary_features and feature_set iterables. Consider the following corner cases: feature_set iterable: 1. All suites are disallowed 2. We want to allow only accelerate_wp_cdn suite 3. We aim to allow both cdn and site_optimization features, thus we need feature_set iterable primary_features iterable: 1. All suites are allowed 2. We want to disallow only accelerate_wp_cdn suite 3. We aim to disallow only cdn feature, not site_optimization, thus the need for a primary_features iterable rifeaturecht|jsdStt| S)zk All free features are available for users Addon ownership check for paid features T)r IS_BILLABLErr)rirns r1_feature_supported_for_userz5extract_features.._feature_supported_for_users5 w+ 4,[-=-=>>>>r0r@status_for_userc|jvrttjS||sttjS|tjkr`|jvrttjS|jvrttjSttjSt|SNr\) supported_featuresrWr#r,r+allowed_featuresr.visible_featuresr-)rir@rnrrrqrks r1_feature_statez(extract_features.._feature_states -@ @ @ (9(BCCC C**388 D (9(BCCC C /7 7 7->>>$,=,EFFFF->>>$,=,EFFFF$,=,FGGGG 888 8r0primary_features feature_set)rIrKr#rHrryrwr,r+r5getr:getattrrh) rirjrkrlrxfeatures_stater@is_disallowed_by_defaultiterable manual_statuswhmcs_suite_statusrnrqs ` @r1extract_featuresrosv.??s????9C99c9L]9999999"N) u  .6I6Z Z ! -6 6 6 -5 5 5:R 5)HH$H$+//66 )6::5AAz%0(;;  G&<""7++sE7MBBsE74FGG>''N7 # #  r0cdtdtffd }i}|jD]`}|j|}|j|}t ||||||g}|||<a|S)z6 Construct feature dict based on given suites r@rrc|tjkr`|jvrttjS|jvrttjSttjSt|Srt)r#r+allowed_suites_listrWr.visible_suites_listr-r,)r@rrrks r1 _suite_statez$extract_suites.._suite_states /7 7 7+???$,=,EFFFF+???$,=,EFFFF$,=,FGGGG 888 8r0)rKr#rHr:r{r5rh)rjrkr suites_stater@rr final_states ` r1extract_suitesrs 9C 92C 9 9 9 9 9 9L)**)6::5AA$+//66 , L . . L 2 3 3.   * U r0cjtjtt |}|S)z Get directory path in which admin's config files are stored. Hides logic of detecting current OS edition environment. :param uid: uid :return: admin's config directory path )ospathjoinrrK)riadmin_config_dirs r1get_admin_config_directoryrs'w||$4c#hh?? r0Fct|}|s&tj|t}n%tj|t }|S)z Get suites_allowed file path for user. :param uid: uid :param old: if "old" allowed modules config needed :return: suites_allowed file path )rrrrALLOWED_SUITES_JSONr)rioldrsuites_allowed_paths r1get_suites_allowed_pathrsT2#66 S gll+;=PQQ gll+;=QRR r0ct}tt||}d|DS)z Reads configuration file (which is manipulated by admin) and returns only that suites which are allowed to be enabled by endusers. :param uid: uid (used only for CL Shared, not used on solo) @return: list of module unique ids cBg|]\}}|jtjk|Sr/)rXr#r.)r]r@ suite_statuss r1r_z&get_allowed_suites..s; A A A)e\"&7&??? ???r0)rrget_admin_suites_configitems)riserver_defaultssuites_statusess r1get_allowed_suitesrsY.//O$% is in one of the passed states for any server user. TNri)rrrrr{rXrEr )r@rusernamerriuserss r1 _is_suite_in_states_for_any_userrs.//O n(##5c::OLLPPQVWW^bhhhWYY  Hh''C 5c::OLLPPQVWW^bhhhtti5$???QQUUV[\\cgmmmr0c8t|tjfS)z> Checks whether enabled for at least one user )rr#r.)r@s r1is_suite_allowed_for_userrs ,E4E4M3P Q QQr0cPt|tjtjf|S)z> Checks whether visible for at least one user )rr#r.r-)r@rs r1is_suite_visible_for_userrs* ,E->-FHYHa,b,4 6 66r0c>tdtDS)@ Check if there are any feature suite allowed on server c34K|]}t|VdSrC)rr]r@s r1 z.any_suite_allowed_on_server..$+HHE(//HHHHHHr0anyrr/r0r1any_suite_allowed_on_serverr ! HHZHHH H HHr0c>tdtDS)rc34K|]}t|VdSrC)rrs r1rz.any_suite_visible_on_server..+rr0rr/r0r1any_suite_visible_on_serverr'rr0c@dtjD}|S)NcXi|]'}|j|jr tjn tj(Sr/)nameis_allowed_by_defaultr#r.r+rs r1 z-get_default_suites_states...sF   * +  % %"* r0)rvalues)r5s r1get_default_suites_statesr-s2  &(( F Mr0cRtttiiid}t|}t|d}tj|rt||Stj|rt||dS|S)zb Reads suites statuses from .json. In case if config does not exist returns defaults. Nr4r5r:r8r6r7Tr) old_config)r3ALLOWED_SUITES_CONFIG_VERSIONrrrrexistsread_json_with_allowed_suites)ridefaultssuites_json_pathold_suited_json_paths r1rr8s !-(** H/s3323DAAA w~~&'',X7GHHH , - -,X7KX\]]]]r0rc0|sdnd} t|d5}tj|}dddn #1swxYwY|r1td||Diidd}nt |ddkst |dd kr1td ||Diidd}n;i}t jD]\}} |d i|i} i} | jD]B} | | j } | r| | n| j | | j <C| r| ||<td ||Dd |diDd|diD||dd}|j D]!\}}|d ||"n;#tjtf$r"}t!jd|||cYd}~Sd}~wwxYwt%di|S)a, Reads json with suites statuses for new awp version: { "version": "3", "suites": { "accelerate_wp": "allowed", "accelerate_wp_premium": "visible" } } for older awp version: { "version": "2", "suites": { "accelerate_wp": true, "accelerate_wp_premium": true } } for oldest awp version: { "version": "1", "modules": { "object_cache": true, "site_optimization": true } } r5modulesrNc`i|]+\}}t||r tjn tj,Sr/)rr#r.r,r]kvs r1rz1read_json_with_allowed_suites..xsE1-Q/a1o1B1J1JUfUor0)r4r5r8r6r7r4rcJi|] \}}||r tjn tj!Sr/)r#r.r,rs r1rz1read_json_with_allowed_suites..s@1AU(00;L;Ur0r6c4i|]\}}|t|Sr/r#rs r1rz1read_json_with_allowed_suites..s71(++r0c4i|]\}}|t|Sr/rrs r1rz1read_json_with_allowed_suites..s7!!!1(++!!!r0r:czi|]8\}}|tj|d9S)z%Y-%m-%d)rLstrptimerM)r]r@rMs r1rz1read_json_with_allowed_suites..sM####t8,55dJGGLLNN###r0r8r7rz9Config %s is malformed, using defaults instead, error: %sr/)openjsonloadrrrIrr{allowed_attrubitesrtyper$r5 setdefaultJSONDecodeErrorKeyErrorloggingwarningr3)rrr suites_keyfsuites_from_filer5r6r@ suite_config suite_attrssuite_valid_attrs attribute attr_valuerXes r1rrOs~>",:J? "C ( ( ,A#y||  , , , , , , , , , , , , , , , 3 8 0 < B B D D#% !  FF!), - - 2 2c:J9:U6V6VZ[6[6[8 0 < B B D D#% !  FFJ'1'7'9'9 : :#|.22<DDHHPRSS $&!!-!@==I!,!@!@J%9= z8R8R8R+4+<&in55$:(9Ju%9 0 < B B D D!! 0 4 4^R H H N N P P!!!##'7';';>F&&_2244 7 7ME6 8  ' 'v 6 6 6 6 7  ( +SUeghiii  & &v & &&s;I9 I=I=HIJ 'J>J J giddata_dict_to_writecustom_allowed_pathc.|pt|}tj|dt} t jtj|ddttj |j n#t$rYnwxYwt|d5}||dddn #1swxYwYt|\}}} t j|||t j|| dS)z Writes modules_allowed file for user :param uid: User uid :param gid: User gid :param data_dict_to_write: Data to write :param custom_allowed_path: custom path of allowed config )indentclsiF)exist_okwN)rrdumpsrrmakedirsrdirnamer pwdgetpwuidpw_nameOSErrorrwriteget_admin_config_permissionschownchmod) rirrrmodules_allowed_path json_datarownergroupmodes r1write_suites_allowedrsX/N2I#2N2N -a=PQQQI 3 BGOO$89955QQQQ  S))12222       "C ( (A  6c::E5$H !5%000H !4(((((s#4B BB*C  CCc:tj|d}}}|||fS)z Return owner, group and permission which files inside admin's config directory should have. User should have rights to read (not write) config, so we set owner root, group depends on CL edition (see comment above) i)rgetuid)rrrrs r1rrs$c5$5E % r0statuesct}t|}fdt|||DS)z Reads configuration file (which is manipulated by admin) and returns only that modules which are in any of given status :param uid: uid (used only for CL Shared, not used on solo) @return: list of module unique ids c,g|]\}}|jv|Sr/r\)r]rnr^rs r1r_z*_get_modules_by_status..s9    #G^  G + +  , + +r0)rrrr)rirdefault_configsuites_admin_configs ` r1_get_modules_by_statusrsd-..N1#66    '7  (1(116    r0c8t|tjfS)z Reads configuration file (which is manipulated by admin) and returns only that modules which are allowed to be enabled by endusers. :param uid: uid (used only for CL Shared, not used on solo) @return: list of module unique ids )rr#r.rs r1get_allowed_modulesr s "#(9(A'D E EEr0cNt|tjtjfS)z Reads configuration file (which is manipulated by admin) and returns only that modules which are visible by endusers. :param uid: uid (used only for CL Shared, not used on solo) @return: list of module unique ids )rr#r.r-rs r1get_visible_modulesr s! "#(9(ACTC\'] ^ ^^r0statusescnt||}t|}ggg}}}|D]}|tjvs|tjvr||n#|t jvr|||tjvr#tj |vr|||||dS)zD Dict with features per feature-set which are in ) accelerate_wpaccelerate_wp_premiumaccelerate_wp_cdn_pro) rrrrzrappendrrryr)rir rvallowed_suitesfreepremiumcdn_prorns r1_get_features_dict_in_statusesr s.c8<<',,NR7'D#$$ h* * *g9M.M.M KK  0 0 0 NN7 # # # k2 2 2{7G>7Y7Y NN7 # # #!(!(  r0c8t|tjfS)z4 Dict with allowed features per feature-set )rr#r.rs r1get_allowed_features_dictr#s *#0A0I/L M MMr0cNt|tjtjfS)z4 Dict with visible features per feature-set )rr#r.r-rs r1get_visible_features_dictr*s! *#0A0IK\Kd/e f ffr0modulect}tt}|D]P}t|}|st |t |||j|vrdSQdS)zO Checks whether is in any of for at least one user )rkTF)rrEr rrrr{rX)rr  server_configrrris r1_is_module_in_state_for_userr1s,--M OOE(##   C!8!=!=0= ? ? ??Bs6{{6U] ^ ^44 ^ 5r0c8t|tjfSz? Checks whether enabled for at least one user )rr#r.)rs r1is_module_allowed_for_userr"As (1B1J0M N NNr0cz|rt}|r||vSt|tjtjfSr!)r rr#r.r-)r use_cachecached_statusess r1is_module_visible_for_userr&HsG-577  -_, , '1B1JL]Le0f g ggr0ctj|j}tj|j}t |}t j|sdSt|j }t |d}d|dtj k|dtj kdd}t|5t|||| ddddS#1swxYwYdS) z8 Syncing allowed configs (needed for downgrade) NTrrrr) object_cachesite_optimization)r4r)r)rgetpwnampw_uidpw_gidrrrrrr5r#r.rr)rrirrrconfig_to_syncmodules_statess r1_sync_allowed_configsr/SsT ,x 'C ,x 'C.s33 7>>* + +1#66=,Sd;;;N/0GHL]Lee!4_!EIZIb!b  N n % %[[S#~>ZZZZ[[[[[[[[[[[[[[[[[[sC((C,/C,ctt}|D]7} t|#t$rt jd|Y4wxYwdS)Nz3Error while syncing the allowed configs for user %s)rEr r/ Exceptionr exception)rusers r1sync_allowed_configsr4msu OOE  !$ ' ' ' '     SUY Z Z Z H s1AA)FrC)RrLrrrr dataclassesrrenumrtypingrrrr r r clcommon.clcagefsr clcommon.cpapir clwpos.constantsrrr clwpos.utilsrrrrrrrclwpos.optimization_featuresrr5rrrrrrcacher rrr#r3rQrWrhr+rIrKrrrrrErrboolrrrrrrrrrrr r rrrrr"r&r/r4r/r0r1r?s  ((((((((>>>>>>>>>>>>>>>>------"""""" 100000/..... !+          .!!!!!4!!!    S} S S S S ,=+D EE E'E/E) E c= ! EEEEP'.37]8J3K:CC  # c     AC AD A A A AnnCnBS9Tnnnn&RSRTRRRR66S6D6666ITIIIIITIIII   ):4c'c'#c'/c'c'c'c'P59))c))-249J3J-K).1))))@ c eCcM.B    h7H.I&FSFTFFFF_S_T____x@Q7R.N3NNNNg3gggg  AR8S X\     OsOtOOOOhhshhhhh[[[4r0