From 243975027ae178395b1b1e6e1254c41fa9d53de8 Mon Sep 17 00:00:00 2001 From: suman Date: Mon, 21 Jun 2021 00:27:28 +0800 Subject: [PATCH] added PluginInvalid class model to track invalid plugins --- .../commands/validate_existing_plugins.py | 14 +++- .../plugins/migrations/0002_plugininvalid.py | 24 ++++++ qgis-app/plugins/models.py | 19 +++++ qgis-app/plugins/tests/test_models.py | 70 ++++++++++++++++++ .../tests/test_validate_existing_plugins.py | 4 +- .../whoosh_index/MAIN_6wzk7090d2stn8v8.seg | Bin 23641 -> 0 bytes qgis-app/whoosh_index/_MAIN_1.toc | Bin 3628 -> 0 bytes 7 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 qgis-app/plugins/migrations/0002_plugininvalid.py create mode 100644 qgis-app/plugins/tests/test_models.py delete mode 100644 qgis-app/whoosh_index/MAIN_6wzk7090d2stn8v8.seg delete mode 100644 qgis-app/whoosh_index/_MAIN_1.toc diff --git a/qgis-app/plugins/management/commands/validate_existing_plugins.py b/qgis-app/plugins/management/commands/validate_existing_plugins.py index 0095da85..5ca4e578 100644 --- a/qgis-app/plugins/management/commands/validate_existing_plugins.py +++ b/qgis-app/plugins/management/commands/validate_existing_plugins.py @@ -8,7 +8,7 @@ from django.contrib.sites.models import Site from django.utils.translation import ugettext_lazy as _ -from plugins.models import PluginVersion +from plugins.models import PluginVersion, PluginInvalid from plugins.validator import validator @@ -48,6 +48,7 @@ def validate_zipfile_version(version): 'plugin': f'{version.plugin.name}', 'created_by': f'{version.plugin.created_by}', 'version': f'{version.version}', + 'version_id': version.id, 'msg': [f'File does not exist. Please re-upload.'], 'url': f'http://{DOMAIN}{version.get_absolute_url()}', 'recipients_email': get_recipients_email(version.plugin) @@ -68,6 +69,7 @@ def validate_zipfile_version(version): 'plugin': f'{version.plugin.name}', 'created_by': f'{version.plugin.created_by}', 'version': f'{version.version}', + 'version_id': version.id, 'msg': e.messages, 'url': f'http://{DOMAIN}{version.get_absolute_url()}', 'recipients_email': get_recipients_email(version.plugin) @@ -82,7 +84,9 @@ class Command(BaseCommand): def handle(self, *args, **options): self.stdout.write('Validating existing plugins...') - versions = PluginVersion.objects.all() + # get the latest version + versions = PluginVersion.approved_objects.\ + order_by('plugin_id', '-created_on').distinct('plugin_id').all()[:3] num_count = 0 for version in versions: error_msg = validate_zipfile_version(version) @@ -102,6 +106,12 @@ def handle(self, *args, **options): ) ) num_count += 1 + plugin_version = PluginVersion.objects\ + .select_related('plugin').get(id=error_msg['version_id']) + PluginInvalid.objects.create( + plugin=plugin_version.plugin, + validated_version=plugin_version.version + ) self.stdout.write( _('Successfully sent email notification for %s invalid plugins') % (num_count) diff --git a/qgis-app/plugins/migrations/0002_plugininvalid.py b/qgis-app/plugins/migrations/0002_plugininvalid.py new file mode 100644 index 00000000..0f777898 --- /dev/null +++ b/qgis-app/plugins/migrations/0002_plugininvalid.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.18 on 2021-06-20 10:00 + +from django.db import migrations, models +import django.db.models.deletion +import plugins.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('plugins', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='PluginInvalid', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('validated_version', plugins.models.VersionField(db_index=True, max_length=32, verbose_name='Version')), + ('validated_at', models.DateTimeField(auto_now_add=True, verbose_name='Validated at')), + ('plugin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='plugins.Plugin')), + ], + ), + ] diff --git a/qgis-app/plugins/models.py b/qgis-app/plugins/models.py index f0e13322..b6d089ac 100644 --- a/qgis-app/plugins/models.py +++ b/qgis-app/plugins/models.py @@ -628,6 +628,25 @@ def delete_plugin_icon(sender, instance, **kw): pass +class PluginInvalid(models.Model): + """Invalid plugins model. + + There were existing plugins on the server before the validation + mechanism updated. + We run the management command to validate them, and track the invalid one + of the latest version. + """ + + plugin = models.ForeignKey(Plugin, on_delete=models.CASCADE) + # We track the version number, not the version instance. + # So that when the version has been deleted, we keep the plugin + # in the tracking list + validated_version = VersionField( + _('Version'), max_length=32, db_index=True) + validated_at = models.DateTimeField( + _('Validated at'), auto_now_add=True, editable=False) + + models.signals.post_delete.connect( delete_version_package, sender=PluginVersion) models.signals.post_delete.connect(delete_plugin_icon, sender=Plugin) diff --git a/qgis-app/plugins/tests/test_models.py b/qgis-app/plugins/tests/test_models.py new file mode 100644 index 00000000..20dae7c1 --- /dev/null +++ b/qgis-app/plugins/tests/test_models.py @@ -0,0 +1,70 @@ +import os + +from django.contrib.auth.models import User +from django.core.files.uploadedfile import InMemoryUploadedFile +from django.test import TestCase, override_settings + +from plugins.models import PluginVersion, Plugin, PluginInvalid + +TESTFILE_DIR = os.path.abspath( + os.path.join(os.path.dirname(__file__), 'testfiles')) + + +@override_settings(MEDIA_ROOT='plugins/tests/testfiles/') +@override_settings(MEDIA_URL='plugins/tests/testfiles/') +class TestPluginInvalidModel(TestCase): + + def setUp(self) -> None: + self.creator = User.objects.create( + username='usertest_creator', + first_name="first_name", + last_name="last_name", + email="creator@example.com", + password="passwordtest", + is_active=True) + self.author = User.objects.create( + username='usertest_author', + first_name="author", + last_name="last_name", + email="author@example.com", + password="passwordtest", + is_active=True) + + invalid_plugin = os.path.join( + TESTFILE_DIR, "web_not_exist.zip") + self.invalid_plugin = open(invalid_plugin, 'rb') + + uploaded_zipfile = InMemoryUploadedFile( + self.invalid_plugin, + field_name='tempfile', + name='testfile.zip', + content_type='application/zip', + size=39889, + charset='utf8') + + self.plugin = Plugin.objects.create( + created_by=self.creator, + name='test_plugin', + package_name='test_plugin' + ) + + self.version = PluginVersion.objects.create( + plugin=self.plugin, + created_by=self.creator, + version='0.1', + package=uploaded_zipfile, + min_qg_version='3.10', + max_qg_version='3.18' + ) + + def tearDown(self) -> None: + self.invalid_plugin.close() + os.remove(self.version.package.url) + + def test_create_PluginInvalid_instance(self): + invalid_plugin = PluginInvalid.objects.create( + plugin=self.plugin, + validated_version=self.plugin.pluginversion_set.get().version + ) + self.assertEqual(invalid_plugin.validated_version, '0.1') + self.assertIsNotNone(invalid_plugin.validated_at) diff --git a/qgis-app/plugins/tests/test_validate_existing_plugins.py b/qgis-app/plugins/tests/test_validate_existing_plugins.py index 6746e5b1..1dd9c849 100644 --- a/qgis-app/plugins/tests/test_validate_existing_plugins.py +++ b/qgis-app/plugins/tests/test_validate_existing_plugins.py @@ -5,7 +5,7 @@ from django.core.files.uploadedfile import InMemoryUploadedFile from django.test import TestCase, override_settings -from plugins.models import PluginVersion, Plugin +from plugins.models import PluginVersion, Plugin, PluginInvalid from plugins.management.commands.validate_existing_plugins import ( validate_zipfile_version, send_email_notification) @@ -16,6 +16,7 @@ @override_settings(MEDIA_ROOT='plugins/tests/testfiles/') @override_settings(MEDIA_URL='plugins/tests/testfiles/') class TestValidateExistingPlugin(TestCase): + def setUp(self) -> None: self.creator = User.objects.create( username='usertest_creator', @@ -72,6 +73,7 @@ def test_validate_zipfile_version(self): 'plugin': 'test_plugin', 'created_by': 'usertest_creator', 'version': '0.1', + 'version_id': self.version.id, 'msg': ['Please provide valid url link for Repository in metadata. ' 'This website cannot be reached.'], 'url': 'http://plugins.qgis.org/plugins/test_plugin/version/0.1/', diff --git a/qgis-app/whoosh_index/MAIN_6wzk7090d2stn8v8.seg b/qgis-app/whoosh_index/MAIN_6wzk7090d2stn8v8.seg deleted file mode 100644 index 2d585eae5ea505828175b858a378bbb5a73d8b3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23641 zcmeHP2~-qUy6%0cUg>5>NGqt2C~h-xIYto|(3Z$VCoWL|rCGubjbMz5nnZne3`R6@ zdopo}&L}PzF*9m3nh}k0$%@fYG>&F56OCq$zPP-5`~KB+tGg&XhI#KKr|*%f@Ba0D z|K0w&_jXksB@&#*_moKFos&l=_i|_9pg`wni6o;?GO)^Rl3J~RfZ;i%Aq4ashd3Qm z@t+d?A@4bkd~yDM;Hx}*ae*`v1ZqxDBwB>@MNmKs3R6T7xM{dVBm_yBSVRzoDRL>{BlwE$|b;ufkS-p`Y5l106Gc_#5+ng3KY;$ZiRS9 zsp>!ijjj-n4z&U35UmxhM5{U<_|Ry?7w=W|haiAPV?m~9ziJ-mDWn;h1-V?CrBdHH zMzatpaK&`!FIpm#R9$**bLoXS;hu6NEJ6e}X?{YeH~IsWhLy2gsgO$Bg|9M8Kqju5 z%2$P=th>}=_6m)+K_~aIlBR&_NLIQmp z2*@qq7H~6#pkjen3&b0&zv|TjY6TH;Zy4s)f>H;!}Ac7!%&oE+|+A z0vHqi(k`gD1qv7wucci`5;z(p&}g(TOF$Nsq~YNSZa^ObccNSd`h!M0sjat=`yeag zQqwHGixcFR0v|dF@x^bXAiOZ)0-*lX)F}qbWNwZ`x{sX6@#v=gI51Gs9&n#pIdr?i-~hrYuX4m& zfMxR{kIlj@KuOz`oPCco?)`)p36zwHroApad?*>fMsoCV^AAh#)(s^^?Zqz6V1i9A zkTW@k3=G5@D3q)t$(bBiOO5#1F-n%J_;vrE4v(h zA24%6kc^Bw3O;y>T+{LDW=iXeV-qDSeh%tMasRX@l8mvba6!~yf~CB;+S}p85Mnp4 z^9a4b{7!~sV$$^5KBsax!O}@yG*4Fb@1YY&Mit&<+&h_ISws5wTLEiMddMPR%AnKf z^Zs|B(X4#?-2vI;n&}M9q4A;)L!T#k zHD0$o$vSIC9?58=9wP!5DkBO=UY1JRdp=u+XMdDrQA_?Y5l^)!1qE;K_A+4OKw|Sf z{@ksyj93FI=&Pw~9|ybid)iLpr+Ur9FAh)&g0UjGErn_L86--97Zamvz^~$SV)H#V zCiP;=zE5B6D{YUTM4)7b_L1D!{e7nsWEc{)_&k1tgi_$2$=UZ0Vwmu8kSn|T( z6cA4axQBc_JauywtUW>J7v}#C`pewp%OsW_e;tp1-J_)E&DArHF9o{=;*qc_)-7xx zNKr`6^_2xMw)YXci?`KXJBmUs|0U&|Bd$v3TkmqTPl0~5aE~% zr+!!mSbLN9*1z!W z+i4v8{5R)FUNw70?tZ|^%QT0^mx{(;B6;1IpL;NX^&4rJibf#V%;kKrj9d%Gdm|PnAglm; zF=bysZ1@-~hFL$gh{)nSSVdCsqhQt#6<@)Rf>}Rbv$a8O5yQX_;ph?{%yL2z3HmK0 znG=X&mS0Kn#V}h|HO0r6wQr*E0g8h$%W0zQ-k9ZFr#O#-!B41$^COC(A42=8B!_dys^gf|915vhp4;v5QBAwrhSkd05Q)*+gkEX6*+kyEkSzO^5?^h|+NU zUyQ+jl#TNFu$a~ML0T54QaFe5DTY~X72>mP+)nvvr2ITAW_>nOT5rs9Zc`kL!Ty+; zv;W61TUIPp*27}xtH;Js+DE~xp9NIgYbl=?v-R9V;Zq2M)`lRPY%D`wW_m~C%5WyhGcS5tO3u2L-f7;H0ZVqKc7Tt|LpK}K;6&M_HNiprg78RgER z8oR{BOf7X}I31a3Q>NG0rCheCu*NQPnKK<_Q%iG;ow-GYAd$PYna^hwW*4PRb=KGw zo?LEbja})I;giaxEzBrzfI#gED9)IgmyzvAqpTViQ&x;#jHNjpmB^3Qr67PQcWHAA zGm&w6v7^Q%O|Efi-1&S5s!?%yyu^Th5amf$p`SeWrCp_yq>H8dq~FV;WT~=wvIf}| zd9XZ5K3%>=epaDV^j8!rY89U=^~ywLrLsRR#9`x?@QzFc8q-LEli?3)=!oX!27f}xzaUvx2pJa0*DsrUsRLtdHK&}$Hz z`*jcz+L+miT4}gd0-uU%D<`jcCS_Da5A#3PCxj2a6Wdk!KXW?97mtq%iP=-~U5~lR zwcZb{pS-X-YDt%mD(`09JzxLB-x}V$rd=Mhuzy2& zV`gNRX@}#378@QI9JzN^lsit$cTCDDJN&A_TEI*muWovE>#;fd>g=n%Zx1@&yZ*-! z5vy1A-KDzv$EWwyK9Rmn8^3AfnRYeV=__B#7}e!t*ZG^H-(K79+O2-Gudf?dJ0fo0 zlk#g122Y#2=(Ro0xoZzU9(lQW*(YxddhQcuT=4ucQ7OBw?uvQOb?#16zsY@Us>1_E zR(&7z0`N1l$040!2cMM>|nfEf*g@{cY5pdsr>$I5Og|LXEsze(e-tT#2^ z{%mOT(%XyPs$YHawWPaus^0tdmU5ZyNP%==vcWx+%EYm~67wHCc(A!j7HgN|w&9$AuoK+EE=h*N}WQ zW_jk7u;88zK|2*eJ9mfd{6;Fd7-6#d-TOPoA36Tp%0DUiXH5Tc;$Lf9-6^aV*oa8& z(pEMix6wxAMyh;te*1a72fsDB{b)r*YE0)HF}+T1uYPxHb;nKB@4QpJbzk))ljKAX zs|t1{rv=KA*d_e3Zsv8%{8TOp)63`kWn>@t|J@}*o7Hf8IDg#QcC+etFS3*OcaFbv z9_?q2KXUw$XgZ{32v1M!+pv?2 z)c`ZpFE1;pm9pZj#x^UfOuVcUi>=x=D{FKsWffU9ZB|wb%ZX>aHdrlC)^dRdAl|Vd z_y8o)+~JUO)10{7)q@VLI=HIqAGhI8xMJU2I_~uq+2b0|J=`P4Gp$d&v$Vkd znX;-VE33?bz6{p8ROr*+Y-dhQ${*rgnu4OtT=YG2W=+zdFJ7*9-8d&LcSW_}3VlQz zKeZ?y`^%B1Op4D@*yrRZLAbKA+!ZS<!Vu> zKD#3#MaNm4;`MBuoBSyG3Y=esE4!MNo8eWHV7nY~_d;{)PlW%=%(!K>( zWlr=zL1$9q@*UEqxcCDT-GUf@X6{vVMR%WJZKV^YOs7h(#Bw#S6IuxF;xZ=$<7}i! SsgL!DP#BlTS1D%J#Q!fEbRWY2 diff --git a/qgis-app/whoosh_index/_MAIN_1.toc b/qgis-app/whoosh_index/_MAIN_1.toc deleted file mode 100644 index 1d9c769d7da608a28dfa9ca73c134f8ee7636c43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3628 zcmaJ^cYGX26+X$5EvFOboG8ZCS;U&pO*D#oB<6Wp8ip-bQ=7_qIqn z!z6OR;pA+9;0?W*ZmOxKw_rjKUC$qSWV~46K zWHE|v80bbAxY*eOk=vc`8yVl19~f0|Il-*p*rjS+;w8th>xY?#-RUdR;#+=iI^`?< zZnft6R>1n2s})oTWhKW|S|@?fOx4HL1ze*pK?&Rm=2*0YujE;UO^>C|3a%xLbsX0x z?z8Ed$9&&%9X!wUn4+7st7S6gYke#;_+xZwP`=RE>bq4t3l-?^MFEu|aK2!Ar@V$8mhT3f&+Q+{^I^Kxy5g zg2>eqIbNp1d2l|6Sc3@R))Z%+HEG001Gkoj@JY1t$s8|NC0odGO4l}1*NY)#!*X<8 zDSPf==J+g7aC-r-P-R-DtN`#z8R`HSUL{9{Q^Kp|G#HZ%uaQG~y^7b$M9|@ONL$?v zJ=`g6M5(?65txI!q>ZYiKLMn43`mpZ=&XVc(0&Ep4`ZBLWPCO0ICL?h}e@ll(61c z4jSIBdcgdCSp^DK>1Btbt7@x7c5U08(%o{I=;mXsp=}`Jlt&_#8g-LIv|L6U$;?pg z2%Yq6%(g8$mp7}eUG%JzXqByL^pgmQRXPURI$BZLXOe$@hZY^74aXme0vo#F#jSY?sj|?h!n2z`ij?YxJ^};(!ia?bD zV7euSToU^L-Xwh>7D#Eh`J5uOU8kbpjLc!tqSzeC?o6Eu9g7Zux6Ep52*1Qkt7_PK z%{ENt7PW@qfkl1cRyxabma<`R+9GJj zq>j*_6|)?VwX)$h%9dakskA<6*yM0@Ok_{|W|A3Wx;bv#Ke!(Ktut=^6R+N};dX|*)q*osY(UD`0 zcc!xYLXIyIvisshc3;Brr7g1iG7w$qG;La*Tg1z$rzujTkU;had!>j_+h{|y}9*b4rp1pJnz;8qDw zf`EE6$G4|tr+iXVl)=c>KIj) zg#EM(`};Y5APxHmIetil{liJvKf>{&En)wd4Ex79e&T_`{z;B^wYu`DbHgrbv}TwS zMuq7ME}fAseVXIlsY{>X_*vo7=MtAb&+!W_E`3qD^d*k>JdjIY=J=IXm%e(gOX40C zu;~ELg182JjpNr-FYe{|4dKN%6ED8S@!Kt4dPgI&-M1270fup6#}Vb}v%*b5_&gMB~^5e`5eMqv!Dhl4N<8r%S)gZ&_nKWug| z5KRk2OZpMVAFE(M5zHKvpaP3}2#8Mc6OKP^J@3!xIM7@)D1XZz`w$A15On1Z*anZlLh=coHXE60sjG~3^-lDf5K@4&J^%paK?bM1^l-P zXW>2;$~&W8sypdd#eX>dH!Sv&PvSn5nd!Kb%Rwenh@%b7?-S8j%--Z-YaDftZyjZo zDszJPc-(U&=CK-e%OeSj$5F>f-*7IDI(=5LN^!LA@~OiU+qPV>rF5AeINK+;$I)`S z^AltYZPAMHt^IO554BP++O9caTU9HFvop~u`GL^2*n3^8?#J0nqVD