From 84f416f6b06d6f5c6d836d2ee106354d02ae9e49 Mon Sep 17 00:00:00 2001
From: Abdulrahman <abdulrahman2.ali@live.uwe.ac.uk>
Date: Fri, 29 Mar 2024 23:56:22 +0300
Subject: [PATCH] Update AIEngineer model and admin functionality

---
 mlaas/__pycache__/settings.cpython-310.pyc    | Bin 2637 -> 2697 bytes
 .../ai_engineer_auth.cpython-310.pyc          | Bin 0 -> 1148 bytes
 mlaas/middleware/ai_engineer_auth.py          |  28 +++++++++
 mlaas/settings.py                             |   1 +
 .../__pycache__/admin.cpython-310.pyc         | Bin 331 -> 974 bytes
 .../__pycache__/backends.cpython-310.pyc      | Bin 0 -> 795 bytes
 .../__pycache__/forms.cpython-310.pyc         | Bin 704 -> 823 bytes
 .../__pycache__/middleware.cpython-310.pyc    | Bin 0 -> 1228 bytes
 .../__pycache__/models.cpython-310.pyc        | Bin 2099 -> 2171 bytes
 .../__pycache__/urls.cpython-310.pyc          | Bin 701 -> 725 bytes
 .../__pycache__/views.cpython-310.pyc         | Bin 4854 -> 5902 bytes
 prediction_service/admin.py                   |  16 ++++-
 prediction_service/forms.py                   |  10 +--
 .../0009_aiengineer_is_authorized.py          |  18 ++++++
 ...9_aiengineer_is_authorized.cpython-310.pyc | Bin 0 -> 593 bytes
 prediction_service/models.py                  |   2 +-
 .../templates/prediction_service/login.html   |  51 +++++++++------
 .../prediction_service/register.html          |  15 ++---
 prediction_service/urls.py                    |   4 +-
 prediction_service/views.py                   |  59 +++++++++++++++---
 20 files changed, 160 insertions(+), 44 deletions(-)
 create mode 100644 mlaas/middleware/__pycache__/ai_engineer_auth.cpython-310.pyc
 create mode 100644 mlaas/middleware/ai_engineer_auth.py
 create mode 100644 prediction_service/__pycache__/backends.cpython-310.pyc
 create mode 100644 prediction_service/__pycache__/middleware.cpython-310.pyc
 create mode 100644 prediction_service/migrations/0009_aiengineer_is_authorized.py
 create mode 100644 prediction_service/migrations/__pycache__/0009_aiengineer_is_authorized.cpython-310.pyc

diff --git a/mlaas/__pycache__/settings.cpython-310.pyc b/mlaas/__pycache__/settings.cpython-310.pyc
index f788d33ee151854c64446ae4eca1f0ed4bd8ade1..b40f363086c9c9309b27a33e6a79f41a8a3dc175 100644
GIT binary patch
delta 94
zcmX>r(kaT9&&$ijz`($uDbJq9DYTK#n3<7lvJ>-JL#y1J#KdB~+{~1eoYeBfqEx-a
t%=py2^vt}})S~#r(vl24M^9HM-?6kLWAaUA`OV5K_gNWvCo^+-0RY|R9LoRz

delta 40
wcmeAaJuAYO&&$ijz`(!|XTz4(BDj&yn3<7tvJ>;!&E71ZSs8gI+jDsV0JpmdjQ{`u

diff --git a/mlaas/middleware/__pycache__/ai_engineer_auth.cpython-310.pyc b/mlaas/middleware/__pycache__/ai_engineer_auth.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a1366c37d9f748f5ce6c1aaf8ec1d9ecd4d7f2b0
GIT binary patch
literal 1148
zcmd1j<>g{vU|^^fW=|_(VPJR+;vi#Y1_lNP1_p*=Ck6(F6owSW9EM!RC`LvQn<<AW
zmpO_V%x2DE$z_dV1+!Ul*mBvU*clnz8B$nN*jgA;*qWK5I8xYy88kUwf=t(Byv0$J
znvz+Rnp~pEc#FL#wJf!$I8~GJ7E5SxYLO=6Ep8AUP?VpRnUk6f(t?bcV2+YuU|>jP
zh+<4(h+;}%Okrwah+<A*PGM<bh+;`$4Q9|}yCvc1>6(|GnU|Vc<XBpg;hUL~l9O7V
zSd^L!G6iNThz-KdAg_W#q=vDEA)X<HA(%mv(NB}{7EgL=NqkXiaY24wajGWMEtcZc
zoU|f#1_p+e3`Lv_3=F?C^%DyU^mB6(6N~k8;kM`}X2z#N?T=3^Ey>U;sJz7yAD@|*
zSrQ-50kRHcFBfB#A})vO!BnHTn1z9X0i+%5;syo=h8o5!h7!gU#%9KBrXs!?h6PMD
zj0+iSnQEAV8A_OI7*m*<nTjlH7_(TiSc@#H#7o$+*t0l5{1oP1##-hY<}A(>mTaaX
z-5TaBu43I1?iAK$#&CvUhH!>FE*6Fowk)1X3q}SIjAY1TEN4KqLzB&~iqF@_(J@%J
zC^bE^xFogc7E38OHj8)|7#MDGBLzhjH$-JletKq}Chsklg2a-HB2Z!jhv_Z$jKt!^
zl9D2bPJzr~aM-2hm1HI-mZYW>v4RX_&rixqO)e?E#hjj6a*L%XKPUATFH~uMQD#+Y
zN)ae*Z}GU~rxyF=m$+7B7MEzU6oG;bl;#RcQ;SPL2@w*jw|GFVjW2*CI&h>y2vB+e
z#aVJ<PELG0Hz>|P36GDFi;0C%h>3|&fKdR%Zs22NVPg8n#lnI=HX-KtX|jS0%}dNp
zjgP;@6(66QpHi9wV)Mku7nUaGKxB$Q_7zDoFhG(S#6_GSF34F$Yzzzxpj224VsJ2U
zF!C^i#r!lmZwaJiCFZ5)>lJ6@7nLNJmJ~yRgBvPbT9i`^4)R-4P?6;Pypp2KBt39C
z&CO3q%_#;I3Jg(_1)$uTT#}ie7hjxORF;{Xst1(^#RS+!B$vURcZ<UY;ww8wP^f`i
K%)<zQLQDY54jqgD

literal 0
HcmV?d00001

diff --git a/mlaas/middleware/ai_engineer_auth.py b/mlaas/middleware/ai_engineer_auth.py
new file mode 100644
index 0000000..6921cf0
--- /dev/null
+++ b/mlaas/middleware/ai_engineer_auth.py
@@ -0,0 +1,28 @@
+# ai_engineer_auth.py
+from django.shortcuts import redirect
+from django.urls import reverse
+from django.contrib.auth.models import User
+from prediction_service.models import UserProfile
+
+class AIEngineerAuthMiddleware:
+    def __init__(self, get_response):
+        self.get_response = get_response
+
+    def __call__(self, request):
+        if request.path == reverse('MLAAS-register'):
+            # Skip authorization check for the registration page
+            response = self.get_response(request)
+            return response
+
+        if hasattr(request, 'user') and request.user.is_authenticated:
+            try:
+                user_profile = UserProfile.objects.get(user=request.user)
+                if user_profile.role == 'ai_engineer' and not user_profile.is_authorized:
+                    # Redirect to unauthorized page or perform other actions
+                    return redirect('MLAAS-login')
+            except UserProfile.DoesNotExist:
+                # Handle case where UserProfile does not exist
+                pass
+
+        response = self.get_response(request)
+        return response
diff --git a/mlaas/settings.py b/mlaas/settings.py
index 1d82798..a74d4fa 100644
--- a/mlaas/settings.py
+++ b/mlaas/settings.py
@@ -45,6 +45,7 @@ MIDDLEWARE = [
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django_session_timeout.middleware.SessionTimeoutMiddleware',# middlewear to delete current session after specified time SESSION_EXPIRE_SECONDS
     'django.middleware.common.CommonMiddleware',
+    'mlaas.middleware.ai_engineer_auth.AIEngineerAuthMiddleware',# custom middlewear that checks if user is authorized to view page
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
diff --git a/prediction_service/__pycache__/admin.cpython-310.pyc b/prediction_service/__pycache__/admin.cpython-310.pyc
index c1504645d10a35ba7f6aa3cedaa99ecc4c2bf5dd..50aa0f37e655a4e3cbe61002b4008c38c3a1f044 100644
GIT binary patch
literal 974
zcmd1j<>g{vU|^WDoGtAz69dCz5C<8vGB7YWFfcF_H!v_Tq%fo~<}l<kMlmunq%fs0
z=P>0mM=^uhEICZMEKw|AHfs)3E^8DkBSR`<7TW^$ROW?@a5gIvn+3#9VM<}kVanx*
z;sB{xz@EynkkOqXg*}C%g&~C_l`)I6nYo!UiYtXPm_d{4CCF`>jJH@5Q*tx&UNSN;
zFlaK~VhPAEF41JX#T{ClS`<)}pO%@Es>yhZ-PgxAKP5Fslkpapqo-?LdS+f~YEd%C
z2xQCz^P&+014Al96k`fQ6jKUg3R5~$6mtqwI%5<|3UdleI#U#D3Tp~m3quqe#CcKd
z5J%nON0{yia@Q@E(&E&jTfCXY@rk7+8Tmz-RjDbr1QH7hit@`+<5Qt7xy4_Unw6Sd
z0vAYTMsgR34Z_Y03=E$I7#J98n6el^&gun)K0`2rCbM72O2#5k{H<iX#a3F7l30?u
zlKB=(acWN5E%u_+!qU{@l3N^wrKv@g#i=DL8Hz+17#Myj=qDBw=ob{Frer3UWaj6^
z7pE4LWhSTUgTqv>pt6XYfq?;}^fM@E1Q@Fn(EO)|?h~92FX9Eo5VN0K5g!8sLlHlS
z5Cjn*<H61;5(9C07#J8NKn!sP28Jqmbo<c4$xoBx7Ds%1USe))eEco0`1suXl+qj!
zn<qZLurx6TD#MeLSzHpIl384klUR9+8_Y|~%qdANy2YLd_IokduSFp1A+AAl7Y73a
z1IW?EAQc=8987GC9E==HJj_KP89z<#D87`e#Ju!;z2yA7lA_F{B2bXsV#@`kyW%1i
zke5JNsECb$f#DWQab`*CEsmnp^vvRt)S@DGkRTU0je^q+*idZlxW!=u@uD3l#TSb(
UFfi~i@GycQE0|>BV3J@200r9SRsaA1

delta 116
zcmX@dews-;pO=@5fq{V`&W0_GgOP#ZF^GeVnHd-u92giFiX$d!N3gO5Gib6;++fP=
zr^zwdk=cfGB|{NNe-YQ@4~(jcw>WHa^HWN5QtcQ)TKE_k7<d?X7{QR0hf#nL05iT4
ANB{r;

diff --git a/prediction_service/__pycache__/backends.cpython-310.pyc b/prediction_service/__pycache__/backends.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f347b86d68c7846d63dc5aa6f3fd08b19c2af62e
GIT binary patch
literal 795
zcmd1j<>g{vU|`UdV^51=Vqka-;vi!d1_lNP1_p*=9R>!56owSW9EM!RC`Lwx6s8pB
z9Hw06C}u_mcZL*}6xJ4o6xLM6X67iC6t-XnP4<@{b2J%m@%ZMaq~<s!CTFMSrMzTh
zU|`T>yv60{>6(|GnU|Vclnhdbj6rsS_{DMz3=F9ZQH&`JQA{Z;?F?y*AX{5FqnO(n
zSQw&Mf*CYfZ}B>p7MJAbLe2L}hUo^Gz|O$Hz{<eDzzy<&4+8^32}3hO7Gn)#8e<Jp
z4RZ?P9HttUC5(NHwX8L)DGa5IMJhF{Sxi~XDNNZ+MJgpMS*%%XAdwX2UdCFs8n!I<
zVwDtzV1^pjU<OSVKTW1v9HqsnMR|$2skb-^5{rw=^NUh$aVKWRr$T+F$#{zeq(qbB
z7He^7L2A)0p2X6UjMTi6%;dz9)LYyj$%3N%w9K5;TP#KSIjKb;AKYTkPs&P7E-Ajn
zoSs^8i#M}49;7Y5D6=XxMU(v&OL1yW+Aa2?)WXu#;*ugZ1_p*AkZ*6XWtS%wr56`*
zf<!nN7#LPE-r|gpPtHj!E{>01$?!{AKe3=dzn~~JB{R7sGe0lBIJKxOGdWd12@*ra
zdIgn5pa25}Trm#=1A`Q!2$KLK8zT!N3saR8N^t9e90l`>CX=6^ChIMZ_;^rw#K+&_
zijU9DPbtkwjgP;@6CYn#nwSHT0h@n|7wW9!)SR67_#!coi@}5lh$RjpKyCm9M=^-t
zU=U+00*QcZkx9u)%uCPLOU}<LDauR&J46rWg(4;f28LT~xuAqs3=U7QJ|ru^_JFLo
W#bE<+qa7$^7J~wkhk=Jtgb4umg2o~M

literal 0
HcmV?d00001

diff --git a/prediction_service/__pycache__/forms.cpython-310.pyc b/prediction_service/__pycache__/forms.cpython-310.pyc
index 65ce3999e709adc67bd43d6741df0fb5ab8029d8..799a389ced0edd5b3172d0368cacc42516d299b5 100644
GIT binary patch
delta 441
zcmX@Wx}A+TpO=@5fq{X+WFlMI=83!kjLZ|`q@@Hxi&Kl7i&7IyGV}A?@{4jc8E>(G
z#F8fpO4ge(FfgPtL@}l?L@}i@FJM{75XG9xoW+*Hn8K9Kl**jNp2FPA6vg4rkiwF}
z+QN{++RPNinZg##pvis<Y;;g+dS-D+Y7y9Irduqf#i>O_EDQ_`noLpLiJ9@KdFh#X
zsi{R(+>V|Ku27C9(=GPojQmXQ<kaF@Y~`6L>8T|Xp9L_oPBv#$XS>Bxl%JD2IgU|7
z24v7J*4+G*)SO#vX_=`xDa9)pii8;$7>a}^FJiP77G+>y@YCcf;sXisg9w4i9~ebb
zKp}C9+c_gYGda}_r0*7YP-04EesF3|YH~>tFGwXwFVrj$7i_8sh{ejlzyQL<91IK$
z91I+cB8);zMIaGBP4-)CDOrhm>G?%WlQWs*8JQ=0FezAo+zD2I&AeM2Ho5sJr8%i~
Sj0_A6U_*Hrco=yYMVJ6I3uy`f

delta 352
zcmdnac7T;PpO=@5fq{V`&W0`R@<iSMM%IaO()BE%#i>P_jJE_pv~y8vVo7Fxo?CuV
zZZb$MGG=CAU~phyU?^5%U|>jPh+<4(h+;}*Ucj=DA&S+VA%!u8sf8hhshKH?ErmIl
zL6ZeyW>9K+W^qYs5mqyqCVMd2F|tf<XH=iOg;7HWWXCPm-29Z(oLg*ZnW;G`#VZ+#
z_!$@&iufo0V6@H_WME+M(_}9K`J{*&B+dgOm>3usZgIKhCT8ZifpitIgG51!p_)Nl
zurUH47Ape-0~^RIAcBK|gHed72qfmG$$pD1B`Yy6J->))@_i-+M&`-;ndGHdV45&Y
Ln=HvJ%g77>KsrQu

diff --git a/prediction_service/__pycache__/middleware.cpython-310.pyc b/prediction_service/__pycache__/middleware.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e3a3ac86bb3d10e26b2aedf08e11f03b7a7b2656
GIT binary patch
literal 1228
zcmd1j<>g{vU|<Md&z3fynStRkh=Yuo85kHG7#J9e%@`OMQW#Pga~N_NqZk=MY^EHh
zT;?cdMursT6qX#8T-GR7Mh16=6xI~B7KRkIW~L~%6!u^SO^%l!6EzucaTKMdWEQ0+
zmuNEH;&sf+&#TPMFD(u&PAz)L$iTp$$#{#)(bF|AJu@#gwI~^+2^llNoT9?Oz>vxi
z#hAhn#gxLB!qmbL#SC&n3quqO#PTRsh{d<W9ZO3x@{2O75=%1k^L#T?QgTwu6N^%l
zL59H$2eCoe8RSn;aMUo?FvK&YFa$HKWb|9fc#9`JwIseMwYVTZuQ*kc=@v_IYED`a
zCj$e+N`@kC1_p*-s``lq1^NXb|0RQLiZ4zrD$7hx)z5`nsaH^Wiz7ZhGcU6wKAs(9
z706C5#wrCIZq$P*MsX}CLO>YoSUv^@h8l(i3^j}k8Ectpn1UIKKqeP)fI^eG2;`Sr
z>_w@CrK!awpwNf-0PJK4!Nb770CH7wVopwcJV<>p3j+fK7b6Q^cR`dVv%*4<fq{XI
zfq?;JE!bT-Aa^llF=R0o8I&;9FlI5NFg7z48G%??%vmfcOxa9DCRM^EtXXVX>>$w;
z=3d5H)*99<j$)+}&J>nr#&CvUhH!8surQRcW^q;OGctf+Bv`B*OoE~agf&_HZm|~>
z<)>xlq~79A%#2TkCL&G7TP&r;sYO-XzCMnQ!MZv5>6v+&+(p75e+y(5$0wGSWTfVm
zWF{w;q^8_r&qypzEGa1}5(LS!6y@in7J)o@i#<OnD>b>K_!e_|YRN5Ls76r2N=+#O
z#p5j=m;BUXzx)!{ip=5?O*U}Y7lGpE7H3&zYI%HGX<l*^gqc{BUL3^@7R@dPaf*Z(
z7$6A=DOPw2it>|Fi;Lqy3PA=Hi!d-SC^0fI3NW%Uaxt>~=VM}HWcttZyGjLD3PLu*
zPm>K4(|L)xsqyi*xZ>k;^HWN5Ky04)_`=e}9EeO2FUTzdAVLO2fRZ=FRbUn<!4!ew
z8ib2M5zfKD!N|eP!vYrd(`3ITkdl>{m!7XzoRMEtl3ZF+3<)49sBm(AUP)1Ak{&4J
s^>Xu5Qge!nKneO58<YbIaIj%W*23++#bE<+w;ia&06Tz(5d?*p0NjKvxBvhE

literal 0
HcmV?d00001

diff --git a/prediction_service/__pycache__/models.cpython-310.pyc b/prediction_service/__pycache__/models.cpython-310.pyc
index 50c27cd026bc5a13998e1b7524438bade92f2ef0..86d32afbfa6cf15951ac4193cb4f909a2bd01b05 100644
GIT binary patch
delta 391
zcmdli@LPa4pO=@5fq{Wx?{c;@|Bbx8OpKo=&t{q}D#gISAk4tP@R^N)fq{cTfKh<4
zNNVysW?5xP1_lOA)>~YTp00W6nR%(HMMdlk3=D278E>(tq^2d7=9El+$fP5~<CLGD
zlbV?4mYJH962+TY9G_TPl96AOS(TbHS&><kUygx+L7ahsp-2`)$W5+el4X>cJcmhI
zD1|AQL6f<N8zc@g+fQ@yTxL5#5MP>sfuWcM>?RS$$<8dTtVIe83=ESmvJ{9aF)%R5
zgXAG@=3$g#EK-^r#=1~NnSp`fWeUjQj77W*3=DonAa!7OYcdsafb3D2EX&rdrU7DV
zf(TI%p~t|$aEmiIr!*bxi(4$kIi=}EGLz4-1&V`gi(=2s$<0qm&AG)~TvAkI0CI^U
mvnZqXWFK~UM(xQt>?IPQkSqfE72+R|wjynaLXpWl9O?kdqEc-D

delta 375
zcmew@uvvgNpO=@5fq{X6*MTj~awBgq6Jzn@*-W!VB^ekPgc%qZirE+#7&sUN7zG%M
zBquLm6`35*%)#_oX7U^+>B$BxY$CU~96eq0(lhf?Q;Uk&85kJ+R&q@4W7e3Q%_1r+
z%fP@O&cML%nFVZ$2xE~f)C^8B83qOhP39tQ1_lO*z9KmW28PLs%%YPUSU6aV<UzcN
zEUlck*i%x|5=(PRCQGvxh$=8JFo2|>4&z~zVk}aaynuC~nj!-O!^;$qsf<OuActr&
z7OB8Y*JLW<0I^jjr?PbmsDqdqAVL&G=uTo6Wt5&Q#vUjRGCqnuHzzkgB{k<3b8$&g
zkv_;Fip-*lS_}*f%Ahb20{e!C5d=Ay_!tEkg_wkxinJzgVK0#Yg<KKH;}EZb3@ifa
NoUF(!GC71p9RS#tLeu~N

diff --git a/prediction_service/__pycache__/urls.cpython-310.pyc b/prediction_service/__pycache__/urls.cpython-310.pyc
index 02683f73fd283f2eac80e14d202a8d1914655123..3994335e1991fecedc1724a0dad612742ac43c45 100644
GIT binary patch
delta 283
zcmdnXdX<$opO=@5fq{WxmjZj*)``5bj4LK;tJkM6rLg2M=dwkyF*2kwrm&{6X0c~+
zq_Cy1_cEq%q;U2!r!uB+r7~x6rf@@fJgIDO8QxUZEUqk$6h5$eey9q8ROT%16hSCY
zD3v*jCq)>_6G>&x;!P0+@zU9&4Ea*Tf*CZ$UxHkw$#{#UAh9IlB_jg^gC^rG*0Rjh
z@?uTKTim`rj*h|cIr-_Cc@sar7UjRiosyN9m!7XzT9i{<#KgeBP{cO*Bcmp35i0`&
t!(=I@05&0zpwQ$3CSw^11_lNm1|CKpCLTsH7CsQk$j8LT$j8X>9RM<lK)L_`

delta 259
zcmcc0x|fwVpO=@5fq{V`&W0`R@<d))#$^+=)$3CkQ&>`2v)HoOQ&>~jdKpvLQ#g8=
zQyEh@Q<<|kQn;WzZmeo}QdzS&v)EI3!8-Y%YWY){v$#?Opgh4;<}B_MAt+Bcl{t$i
zMFhl4XOH4dQ4kGg&=h+Ka+fCKEtZ1Bl8l#(3=9mKjJH_JGE>WoCo?g=7UjFeosyN9
zm!7XzT9i{<#KgeBP{cZ!iAi&^0aE~*Ac!kCxsAzKN{oSlfro*Ik%vi)nU6_~QH+s~
LiI0(wk>fi6x!5^n

diff --git a/prediction_service/__pycache__/views.cpython-310.pyc b/prediction_service/__pycache__/views.cpython-310.pyc
index 75ea0217cd183b744d09f743647419b2ebea4e96..3bf7b8c4c54e6585584a01ac3e09da23a139bd58 100644
GIT binary patch
delta 2015
zcmeyS+NZ~t&&$ijz`(#TOOrj#Nqi!o43h)nM4kM4h7_h8=3JI27Dk2?mK4?;_FRrA
z4ltWHhcj0oN+4G-N-$R_N{Epmg)fD_g&|5fg&{>CM<iD?N;Fq2N{o>q1=$RS6viBe
zT*fHIT&5@{upFvdmK4DpPN;c8DZ*hb3{m1K3@IWx5>XOhS~5x!OiM*cgK3#u*(f=%
zK_WTwQSvDaDWW+Fxr$MWP%)(_rBt>Qu@vzZhGxbn<rI-%22F{LUv4qhYck*B4lPbC
z3Mk4?%gjl=#qOGy0^;A|a`be~OV7+pO)W}h1O*BdvoSC*fUq+I14Ho!1_p*2hAf5@
z#%!h{-x9_ehAgIL##+W2#s$m^8H#*r7#FZCWT<7TVa#G(z?Q<akg=8-%4S~3Sj$pU
z&z{AR#aY8t!;-?%%T&u+!;-?9%~WJm!UYy*O=0V0WMs(WsbNWB&t@vJE8&KUbEI(g
zGBGlg@GRi1VMyVsVV=#9!abLHAxMlbg{PS@m?4k3gt3{Sma&Ath9QMFg|CJ&ld+jO
zm_d`@?-omde{jexj?$Fk)S|q^+|*kvMfo|YnoPG?N{dsAili7A7>cAB7#LPEf~i~F
ziJ9@K(BN>>WP%9tW){aMmX>7X7iCtZrc{YICMV~Y=9MTU7o{eaq^2mO<rgXZVpRM!
zxt7^fK;RZzZfZ$Jeo7HL$Z(0thnUr4L_tg*1_p*(Y!FRFVjvN55WxZxW-l&HPEIW@
zE@B1=F)=VOXtEXYf!K;50_4OZNe~O<;#)i*$Hx~yqH?kzi)6hrD3%l$7#O%1xfnSZ
zIT(2uc^CzlIhX|)IT!^PMVL4knLe@!3NRLFfy`#Q#RKwCYF<fZa$-s9E!Ld;^vpa>
z#v+i5P?7;F0|NsHgOkBL<YeGg!;r<efC(Jg^`I01;(%hCsf4+Pp@y-BDTSq%xt6(x
zIfbE=vB;r@Ig2HW6&&s6C2U#jSxg`iP{h}=)Uaf66q}cDF5s$RNMQ#@E_VtCC~`}9
zY8Yymn?cddox%wgfvDm_R#jgDN*&zIOu-DAJbpzIppXIu*Da2M#Ny)e{Gt?1CP?_{
zf}~_YgbV`%LsfWWeyKuYQK~{-eu)AoNFZ^nP?E2Z2#yeil8jUZU!TOpV1?q!;*!){
zJ%xar)WqUch4RGA5^&TfrsURV=D~F*mSpDV=@o$@ql(Md$I&rZHzPkcwMy1AuPiYq
zGerRud7!kYkYA(#bDmz6Y(Y_KN@g-hb9`}XQCVhksy;YY^fF3vb2Ryilt7LK`%DeQ
z(gr0PZjf08MfvrhJPk?BpcpIyCAA_skTP)UVofb7$}fVXEgg_3IDxT35*R3)ion4F
zPG#V*5dbLy6M|rCz}|=lJI4u>(m+OYfzuctBL@=?qlf?_8zT=R2O}2~2O|$Nh%PeN
z?8)+xiP2=TA&>IpIQCXXtI2^pu9G!6EFmnm?I24WC$HnEV|1LX%c;j^4iQM?^kQ_J
zyoS@5(Qz^(n}dKASeSu<;pGhwAuxF(rv`hGFIaRkBb&kGelAfqN03zXWJP{GHmJ-!
zE(h*tkmw(fN;{C0PZWs%7eu@T5$8cNNpK<o!~z@i3ncpi#PtBN`a!G^5DS!OUcLlz
zlP53aF;ab54ieo663E0PUV_c`oXp53!}Br?Bo8vZ$bRxdo?`ZwE5QPj=kQc==YW|Y
zqbw&c<S7C3U;YR2<KX-vklvRGsQe-u1V0~S2!vk<VuI8c*-U0+Q<}V&pNFw%@+tn^
zJcgk7WXUf`%_~xwJW;@yQEl>3fmp`U$;yHntnCa83`vs%1Y_AiEKQZkn*|qmg3B&M
zaRn+rZV9JkCFZ5)>m}#sl@w(r>49=i5hz6#fs>a3$P%Xf;-V@B28Jlsywco)%A)eg
znL_e1m0*$Ff}9lNTg(BTK1Co071e><+dg@TkeVGRwgnh?n0Od@*uW$s6B8FB2Nw?u
i52FYp2a|vV50e0+04TLFaY#UlI#6-P!N|nK#|Qu}so0JH

delta 979
zcmeCv`=-j5&&$ijz`(!|XTz4pC^(T%hUo~yM4kLd-W0wThA4p)h7|rB!6-p6EfggL
zriG(Kz_e(tSd=&;1DGulC6U6AB9J4QD-|UL6_bvVPGw6GOc82fXl9I(N#PG>&=lTW
zz<7(XKA90@DHJm^Ffgz&FfceXFfbISFfcIGFk~^LFlI9qsh2R;Fk~?`GuATJFfL$T
z$WWwK!?=KDAp;{r4PzGT0=5*Ug^aaKCF~10Y8X<OYnWy;q_E6oUdY7AP{NtQ+RPZt
zkjGrY*vwGNSi)7qkiwS2Uc;El*lfTY%%I8PcZ(&!KRDzTM`>|tQC?zhYL$p%a&mrY
zUWr0-QEFmIYKlTyev!g2M#ZYhYgkMLxNouLrj}&nrxdX>FfbH}PX5TEuFAr|z;KJb
zxHLIAwYazl<dq^O1_lOA<|00jA_)*7Hd&EbSc9V|H9fPqB(+E$<WCU>1_mxBE=CR}
z4kjKZ5k?M1reACv0?bA7n`JmYGBGMoZWL6WY{=cps5yBfr_1Eu+*S}4`^)VhGYuv;
z^3*XJOybpJQ-km~a@zB}6lY*yc=;S6P|s`3XfSyrrvsZNMBpc{F`Es9xslUgauS~?
zn*m6D^yH14;*%!`h{I+19JsweGJim-bz#yzo*=QmAmS~EI1iEygcJTC7TCaFAlVNf
zt~rR+4`P90_oWPo`x3+rn#{;$r24WPB(M=A5P?a&Oah5nOy0;T!}Br?#0HsOq&Jz7
ztC;=eO0dA>e1S@~XbAJ2KqX`J<P5<&ZioQL?1agTTqOv8kv4)K2hs)MCxDn>!?h=G
z<W!nGL70azaq?W@-8>4Q_+`m2NX;vfo}40L%qTl~hDa=9%H(e%8vJDp3=Ec_*bD*1
zCi7%NQQgT7qAZi+M3vY;a+<P}+e8<Lfg=1CQ+{z#CIbUQ6l-2-Zb4;H+T?sOdBqH{
zNNzz+it#Px08gJHkbOnDAm@M#C=viA9exg*-29Z%oK!ndwkg(_d{InXgoA}ch=Y-X
Lkq3&InD`h00=DDQ

diff --git a/prediction_service/admin.py b/prediction_service/admin.py
index 640d4b8..97ce197 100644
--- a/prediction_service/admin.py
+++ b/prediction_service/admin.py
@@ -8,4 +8,18 @@ from .models import MLModel
 # Register your models here to the admin page
 admin.site.register(Post)
 admin.site.register(MLModel)
-admin.site.register(UserProfile)
\ No newline at end of file
+admin.site.register(UserProfile)
+
+from .models import AIEngineer
+
+@admin.register(AIEngineer)
+class AIEngineerAdmin(admin.ModelAdmin):
+    list_display = ['user', 'is_authorized']
+    list_filter = ['is_authorized']
+    actions = ['approve_engineer', 'reject_engineer']
+
+    def approve_engineer(self, request, queryset):
+        queryset.update(is_authorized=True)
+
+    def reject_engineer(self, request, queryset):
+        queryset.update(is_authorized=False)
\ No newline at end of file
diff --git a/prediction_service/forms.py b/prediction_service/forms.py
index 5385eef..c8a56a5 100644
--- a/prediction_service/forms.py
+++ b/prediction_service/forms.py
@@ -1,11 +1,11 @@
 from django import forms
+from django.contrib.auth.forms import UserCreationForm
 from django.contrib.auth.models import User
-from django.contrib.auth.forms import UserCreationForm #django implemented registration
 
-
-class UserRegisterForm(UserCreationForm):# inherits from usercreationform and adds email to the form
-    email = forms.EmailField()# create the email field
+class UserRegisterForm(UserCreationForm):
+    email = forms.EmailField()
+    role = forms.ChoiceField(choices=[('user', 'User'), ('ai_engineer', 'AI Engineer')], widget=forms.RadioSelect)
 
     class Meta:
         model = User
-        fields = ['username','email', 'password1', 'password2'] #place elements and email field in order
\ No newline at end of file
+        fields = ['username', 'email', 'password1', 'password2', 'role']
diff --git a/prediction_service/migrations/0009_aiengineer_is_authorized.py b/prediction_service/migrations/0009_aiengineer_is_authorized.py
new file mode 100644
index 0000000..2b0b747
--- /dev/null
+++ b/prediction_service/migrations/0009_aiengineer_is_authorized.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.1.4 on 2024-03-29 11:36
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('prediction_service', '0008_post_slug'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='aiengineer',
+            name='is_authorized',
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/prediction_service/migrations/__pycache__/0009_aiengineer_is_authorized.cpython-310.pyc b/prediction_service/migrations/__pycache__/0009_aiengineer_is_authorized.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e847c26be1a72baa8ed5e9eba9cc5fa6cac72b88
GIT binary patch
literal 593
zcmd1j<>g{vU|_hkoGonvBLl-@5C<8vFfcGUFfcF_t1&Pzq%fo~<}l<kMlt3xMKLil
zxHF_Mr7*WJq%fy4W-&K2M=__c1T$!|z66<|$#jb=H#5B`u_QA;ulN>QZhlH?PH{3w
z3K_G(EYM+KU`S<%VoYI(VoG65XN+P_WyxX%S&+(>#h${F!rIH2!q&^2&KSj!!XC_^
z$#IL*7iPXD(=DNbqSTbkWRPv~#i>PQnaQcQ_zVmTEaD6Di%a5*b4t^1aV2J^=A~!m
zrKT3$;>|3MPb@9T$S=yQN=<RoWW2?mlA4xSnp2|5e2WY0+W5T0+|*kvV3IX0Gc_m0
zPm}W&M?6?OKK>S0e0*+xN@-4NeEcn*`1r!o#2k=X5HBUQAT=)~H7_|cwYZ3hfq~%`
zhhs{L8_0|zW)PRhDL+3aH8Bq?bc-v$AQc)?D;bJJ7#JYLFK7M4f&zU^pXnn)R^PzD
zz%m};v3L}J=@nEKf#MJp%*8?s3=A9$Ow26*Sy-7EnHaekS^jeT2h00uvfScK$x6&i
l&(}*y0=pROPOv1xK@gTG$O9ZU5Wm|of|3Ww4gn@HW&q(!pb`K8

literal 0
HcmV?d00001

diff --git a/prediction_service/models.py b/prediction_service/models.py
index 22fa64a..d3f147c 100644
--- a/prediction_service/models.py
+++ b/prediction_service/models.py
@@ -22,7 +22,7 @@ class EndUser(models.Model):
 
 class AIEngineer(models.Model):
     user = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
-    # Add other fields as needed
+    is_authorized = models.BooleanField(default=False)
 
 class Administrator(models.Model):
     user = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
diff --git a/prediction_service/templates/prediction_service/login.html b/prediction_service/templates/prediction_service/login.html
index 7263290..47be209 100644
--- a/prediction_service/templates/prediction_service/login.html
+++ b/prediction_service/templates/prediction_service/login.html
@@ -2,28 +2,39 @@
 
 {% block content %}
 
-    <div class="container d-flex justify-content-center">
+<div class="container d-flex justify-content-center">
+    <div class="row col-sm-4">
+        <h1>MLAAS Login</h1>
+        <form method="post">
+            {% csrf_token %}
+            <fieldset class="form-group">
+                <legend class="border-bottom mb-4">Log In</legend>
+                {% if error_message %}
+                    <p class="text-danger">{{ error_message }}</p>
+                {% endif %}
+                <!-- Add fields for username and password manually -->
+                <div class="form-group">
+                    <label for="id_username">Username:</label>
+                    <input type="text" name="username" id="id_username" class="form-control">
+                </div>
+                <div class="form-group">
+                    <label for="id_password">Password:</label>
+                    <input type="password" name="password" id="id_password" class="form-control">
+                </div>
+            </fieldset>
 
-        <div class="row col-sm-4">
-            <h1>MLAAS Login</h1>
-            <form method="post">
-                {% csrf_token %}
-                   <fieldset class="form-group">
-                        <legend class="border-bottom mb-4">Log In</legend>
-                        {{ form.as_p }}
-                   </fieldset>
-                   <div class="form-group">
-                        <button class="btn btn-outline-info" type="submit">login</button>
-                   </div>
-            </form>
-
-            <div class="border-top pt-3">
-                <small class="text-muted">
-                    Need have an account? <a class="ml-2" href="{% url 'MLAAS-register' %}">Sign up now</a>.
-                </small>
+            <div class="form-group">
+                <button class="btn btn-outline-info" type="submit">Login</button>
             </div>
-            
+        </form>
+
+        <div class="border-top pt-3">
+            <small class="text-muted">
+                Need to create an account? <a class="ml-2" href="{% url 'MLAAS-register' %}">Sign up now</a>.
+            </small>
         </div>
+
     </div>
+</div>
 
-{% endblock content %}
\ No newline at end of file
+{% endblock content %}
diff --git a/prediction_service/templates/prediction_service/register.html b/prediction_service/templates/prediction_service/register.html
index fab6ea9..ca1b2cc 100644
--- a/prediction_service/templates/prediction_service/register.html
+++ b/prediction_service/templates/prediction_service/register.html
@@ -8,14 +8,15 @@
             <h1>MLAAS Register</h1>
             <form action="/register/" method="post">
                 {% csrf_token %}
-                   <fieldset class="form-group">
-                        <legend class="border-bottom mb-4">Join Today!</legend>
-                        {{ form.as_p }}
-                   </fieldset>
-                   <div class="form-group">
-                        <button class="btn btn-outline-info" type="submit">Sign Up</button>
-                   </div>
+                <fieldset class="form-group">
+                    <legend class="border-bottom mb-4">Join Today!</legend>
+                    {{ form.as_p }}
+                </fieldset>
+                <div class="form-group">
+                    <button class="btn btn-outline-info" type="submit">Sign Up</button>
+                </div>
             </form>
+            
 
             <div class="border-top pt-3">
                 <small class="text-muted">
diff --git a/prediction_service/urls.py b/prediction_service/urls.py
index 154dbe9..e537584 100644
--- a/prediction_service/urls.py
+++ b/prediction_service/urls.py
@@ -2,12 +2,14 @@ from django.urls import path
 from . import views
 
 from django.contrib.auth import views as auth_views
+from .views import MLAAS_login
+
 
 urlpatterns = [
     path('', auth_views.LoginView.as_view(template_name='prediction_service/login.html'), name='MLAAS-login'),
 
     path('register/', views.register, name='MLAAS-register'),
-    path('login/', auth_views.LoginView.as_view(template_name='prediction_service/login.html'), name='MLAAS-login'), #
+    path('login/', MLAAS_login, name='MLAAS-login'), #
     path('logout/', auth_views.LogoutView.as_view(template_name='prediction_service/logout.html'), name='MLAAS-logout'), #
 
     path('about/', views.about, name='MLAAS-about'),
diff --git a/prediction_service/views.py b/prediction_service/views.py
index 8883186..cfeffc6 100644
--- a/prediction_service/views.py
+++ b/prediction_service/views.py
@@ -28,24 +28,65 @@ def about(request):
     return render(request, 'prediction_service/about.html', {'title':'About'})
 
 
-def register(request):
+from django.contrib import messages
+from .forms import UserRegisterForm
+from .models import UserProfile, EndUser, AIEngineer
 
+def register(request):
     if request.method == "POST":
-        form = UserRegisterForm(request.POST) #fill whatever form we have with current form input
-
+        form = UserRegisterForm(request.POST)
         if form.is_valid():
-
-            form.save() # save the user account to the db
-
-            username = form.cleaned_data.get('username')# uses the data and clears it from form
+            user = form.save()
+            username = form.cleaned_data.get('username')
+            role = form.cleaned_data.get('role')
+
+            # Create UserProfile
+            user_profile = UserProfile.objects.create(user=user, role=role)
+
+            # Create EndUser if role is 'user'
+            if role == 'user':
+                EndUser.objects.create(user=user_profile)
+            elif role == 'ai_engineer':
+                AIEngineer.objects.create(user=user_profile, is_authorized=False)
+            
             messages.success(request, f'Account created for {username}!')
             return redirect('MLAAS-login')
     else:
         form = UserRegisterForm()
-
-    # if metho is GET then return normal register page
     return render(request, 'prediction_service/register.html', {'form': form})
 
+
+from django.contrib.auth import authenticate, login
+
+from django.contrib import messages
+from django.shortcuts import render, redirect
+from django.contrib.auth import authenticate, login
+from .models import AIEngineer
+
+def MLAAS_login(request):
+    if request.method == "POST":
+        username = request.POST.get('username')
+        password = request.POST.get('password')
+        user = authenticate(request, username=username, password=password)
+
+        if user is not None:
+            if user.userprofile.role == 'ai_engineer':
+                ai_engineer = AIEngineer.objects.get(user=user.userprofile)
+                if not ai_engineer.is_authorized:
+                    messages.error(request, 'You are not authorized to access the MLaaS system. Please wait for admin authorization.')
+                    return redirect('MLAAS-login')  # Redirect to login page
+
+            login(request, user)
+            return redirect('MLAAS-home')
+
+        else:
+            messages.error(request, 'Invalid username or password.')
+            return redirect('MLAAS-login')  # Redirect to login page if login fails
+
+    return render(request, 'prediction_service/login.html')
+
+
+
 import os
 import io 
 import numpy as np
-- 
GitLab