From fdec3b37dc77bb9f73b7d890dd7fc7409e62f2f8 Mon Sep 17 00:00:00 2001 From: "cc02503@surrey.ac.uk" <cc02503@surrey.ac.uk> Date: Fri, 29 Mar 2024 21:40:32 +0000 Subject: [PATCH] Update - implemented the event driven architecture with kafka event store and streaming service for asynchronous communication between the product and user microservice --- .../app/__pycache__/config.cpython-311.pyc | Bin 351 -> 390 bytes Product_MicroService_Group3/app/config.py | 4 +- .../__pycache__/getReviews.cpython-311.pyc | Bin 0 -> 2389 bytes .../app/controllers/getReviews.py | 44 ++++++++++++++ .../app/events/__init__.py | 0 Product_MicroService_Group3/app/index.py | 11 ++++ .../__pycache__/getReviews.cpython-311.pyc | Bin 0 -> 2521 bytes .../updateUsername.cpython-311.pyc | Bin 0 -> 2407 bytes .../app/models/getReviews.py | 42 ++++++++++++++ .../app/models/updateUsername.py | 48 ++++++++++++++++ .../app/subscribers/__init__.py | 5 ++ .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 523 bytes .../updateUsernameSubscriber.cpython-311.pyc | Bin 0 -> 2125 bytes .../subscribers/updateUsernameSubscriber.py | 34 +++++++++++ .../app/__pycache__/config.cpython-311.pyc | Bin 0 -> 348 bytes User_MicroService_Group3/app/config.py | 7 +++ .../changePasswordController.cpython-311.pyc | Bin 3885 -> 3887 bytes .../deleteProfileController.cpython-311.pyc | Bin 1360 -> 1362 bytes .../fetchUsernameController.cpython-311.pyc | Bin 0 -> 1293 bytes .../loginController.cpython-311.pyc | Bin 3422 -> 3424 bytes .../logoutController.cpython-311.pyc | Bin 1096 -> 1099 bytes .../showReviewsController.cpython-311.pyc | Bin 0 -> 2018 bytes .../signupController.cpython-311.pyc | Bin 2617 -> 2594 bytes .../updateProfileController.cpython-311.pyc | Bin 1994 -> 2445 bytes .../controllers/changePasswordController.py | 23 +++++--- .../controllers/deleteProfileController.py | 8 ++- .../controllers/fetchUsernameController.py | 28 +++++++++ .../app/controllers/getUsersController.py | 18 ++++++ .../app/controllers/loginController.py | 8 ++- .../app/controllers/logoutController.py | 8 ++- .../app/controllers/showReviewsController.py | 54 ++++++++++++++++++ .../app/controllers/signupController.py | 9 +-- .../controllers/updateProfileController.py | 21 ++++--- .../app/events/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 272 bytes .../eventDefinitions.cpython-311.pyc | Bin 0 -> 492 bytes .../app/events/eventDefinitions.py | 5 ++ User_MicroService_Group3/app/index.py | 28 ++++++++- .../changePassword.cpython-311.pyc | Bin 5555 -> 5555 bytes .../__pycache__/fetchUsername.cpython-311.pyc | Bin 0 -> 2209 bytes .../__pycache__/getUsers.cpython-311.pyc | Bin 0 -> 272 bytes .../__pycache__/updateProfile.cpython-311.pyc | Bin 4493 -> 4493 bytes .../app/models/changePassword.py | 10 ++-- .../app/models/fetchUsername.py | 39 +++++++++++++ .../app/models/getUsers.py | 38 ++++++++++++ .../app/publishers/__init__.py | 1 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 369 bytes .../kafkaPublishers.cpython-311.pyc | Bin 0 -> 2334 bytes .../app/publishers/kafkaPublishers.py | 44 ++++++++++++++ 49 files changed, 500 insertions(+), 37 deletions(-) create mode 100644 Product_MicroService_Group3/app/controllers/__pycache__/getReviews.cpython-311.pyc create mode 100644 Product_MicroService_Group3/app/controllers/getReviews.py create mode 100644 Product_MicroService_Group3/app/events/__init__.py create mode 100644 Product_MicroService_Group3/app/models/__pycache__/getReviews.cpython-311.pyc create mode 100644 Product_MicroService_Group3/app/models/__pycache__/updateUsername.cpython-311.pyc create mode 100644 Product_MicroService_Group3/app/models/getReviews.py create mode 100644 Product_MicroService_Group3/app/models/updateUsername.py create mode 100644 Product_MicroService_Group3/app/subscribers/__init__.py create mode 100644 Product_MicroService_Group3/app/subscribers/__pycache__/__init__.cpython-311.pyc create mode 100644 Product_MicroService_Group3/app/subscribers/__pycache__/updateUsernameSubscriber.cpython-311.pyc create mode 100644 Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py create mode 100644 User_MicroService_Group3/app/__pycache__/config.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/controllers/__pycache__/fetchUsernameController.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/controllers/__pycache__/showReviewsController.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/controllers/fetchUsernameController.py create mode 100644 User_MicroService_Group3/app/controllers/getUsersController.py create mode 100644 User_MicroService_Group3/app/controllers/showReviewsController.py create mode 100644 User_MicroService_Group3/app/events/__init__.py create mode 100644 User_MicroService_Group3/app/events/__pycache__/__init__.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/events/__pycache__/eventDefinitions.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/events/eventDefinitions.py create mode 100644 User_MicroService_Group3/app/models/__pycache__/fetchUsername.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/models/__pycache__/getUsers.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/models/fetchUsername.py create mode 100644 User_MicroService_Group3/app/models/getUsers.py create mode 100644 User_MicroService_Group3/app/publishers/__init__.py create mode 100644 User_MicroService_Group3/app/publishers/__pycache__/__init__.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc create mode 100644 User_MicroService_Group3/app/publishers/kafkaPublishers.py diff --git a/Product_MicroService_Group3/app/__pycache__/config.cpython-311.pyc b/Product_MicroService_Group3/app/__pycache__/config.cpython-311.pyc index f5dbbfc7766e0722ceb9c91c99c512ea13f2f156..24ec9fb0533112f07ac3fe8e36eedc6a3f03e748 100644 GIT binary patch delta 147 zcmcc5)W*!aoR^o20SIDE8Pbv`@=AKi0XfqdQW#Pga~Pr+QkbF`Q<$TeQdpvxQ&^)| zQW%37G}&H)bohnbVskIbFD)?6>=b5TsN&1XPfpCq$S*FjvNW(X(qx?&Bg=P-$J^1( o+c7@aH7LwAXkz6?E*_v(Mj$TMm~6tR#P@(tu7L*xi$Kl*0GsF{IsgCw delta 107 zcmZo;zR$$FoR^o20SF8%f2BH3<drm&0&=D^q%fo~<}gGtq%cJ>rZ7h_rLaUXr!WRH zXtKTpsrC!G#pYg=Us_<C*(uDxpvf|^Kz8Enja=M7IYuBZR-PQjsKnX8(!f&03FHF+ D>K+!v diff --git a/Product_MicroService_Group3/app/config.py b/Product_MicroService_Group3/app/config.py index c00614d7..5ddee913 100644 --- a/Product_MicroService_Group3/app/config.py +++ b/Product_MicroService_Group3/app/config.py @@ -4,4 +4,6 @@ import os DEBUG = True SECRET_KEY = "Group3" -PORT = 5001 \ No newline at end of file +PORT = 5001 + +KAFKA_SERVER= "localhost:9092" \ No newline at end of file diff --git a/Product_MicroService_Group3/app/controllers/__pycache__/getReviews.cpython-311.pyc b/Product_MicroService_Group3/app/controllers/__pycache__/getReviews.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ccdb50ab470f1f972531278c526c941297e5bd9 GIT binary patch literal 2389 zcma(SOK2NMbVkxjtFP_E`MD|H+769sM;1=vCdM(OPMngG*i=qKgg~r!NA}wLQD;|n zEbQV#3ZVqrTSPB4J)|i~A(R$+ZF*>rtFSa-!C)vo<fak=A*a4seQY_0_Axv2KJ(tp zyx)Eok4F%|=Y6Qq&mr^|BbpFsATNFd<Svqtj8&xJEY^HkpXSf{wLmtYaaj&CnNJOB zp=`**{VK18vtf*Uh+sKDBKLd<J%Fzc*(ix_#+uabRp#X2JboBz-!JpG&^_4pptUs{ z2g_kO{4jD410TLRWD|1q7Rq+Wu?$MapEG8XbHg8~B~qk{Zn>dF)6kW|svDx@(-JW) zH^4Y<$Rwtz7<v-B(RpI!DOpy?iV0-=BeAd~&QL=xNrbv#kbdk5%ln3l9@iRf@!Y`7 zbY>Q`LK?9a4B3<#7xNZB%<OydElhWj)w(u9i!EHn?N3@qYlx0o&0v7$BD3Lv>|64j zO8cyElZRmc9t+rt?vn1Y4*~P9VFhQ99FV!j8f0rSbkz-&OhWUDOqm7dG|w$AM<_L@ z8_-LtT0VZmC<!_tvS1m)91&DwejW%#XS68Gf+*DWl0h0`X8hnU3fYF-VBJlWXT*M! z=yJpJc@5$r&Xc5%COp}$pycOP^XytCd%GaK{$X+~ca70GQCpQ3a??7wK$T^ZyI@Eq zjp&w{n*phzi)!wg4gzW_)~a9>giMK2vYMMTO4KC6b%QSD&dbZ9F2VID7erMh`aCh& zORkeSVU|b>x&g0K2w1F#K7U1#sF5LbS&>No5;aQ2lR2?i%t?lBQ3EW%wOZ+6ri!a> zWalaL5WIjz&NN`!Kre%+<KUg8O0t?5a1sL>m$pNR8tUYx@K$u+or%gPPon*HwEtxU z^{4L7SNletzEL~Y`**C@7EV@Ur<~X+J9cWj`)wfY{eYjY1<`?{m4dzhm>oL?MAu=v z=YrjF(dI9{fFn^kp&F8?E*PdYb~b%>1X8za&M+*~qGB-*PG#PbTFD6-LHN8R-UKcr zF|*PD#(5KDY_V83U?+L^rs?Lc6mRZE&{x`%xxF*2<1kvoo4f4q()2$JwCk?>toSZD z*Dl4VO&VPDEwXI&p#9W6J43LOCGdam<Y8y4Q1{xDQ3mxRtGj6lp#enSTKBizD!k_3 zt9Jvs@4EjpKhv*cD|iLn^xr@$I2pO>c1k7FGBhaTR`r&wLjKHi*7;ehvJ{ONC9B+X zrCxIa)S)GqB}oFh02RLaPB}Ph6cuT#9GMZRrC87@$I7AULct`~SozSDsHpYwXC*8& zYIiIdb@_UWgvJ?QBFeJI<>Zo9G~FQ4B||23pU12BXU<~hxZz^+7&mBmr?}yZHziVJ zCnp26gQ@V)JVaTvM7M(y$)GYcjRpe~lVy_tKo0^!nOD839}x3Tm^RQ>;^3Fs7n*%E z^>g5-$S?0#)00km@@e|=ll0|3fXX=OOf@m<BxW~0tocIR(6gStZ-%}ex=$-Z)t(Wj zXXJLr79Y10?^XFhhaa^0K_G80R63l)C#rnP;ZruBVl1^X?HoN_<wqTU)aFMSOR4la zM~16>+Tqi7bG+J$cGnQ*hIS_JfOqeAwT^&O_Ka5mH9u&<Y94{7{pveE@WFBP_;_S8 z?teVeIm!Ef<2k^uCOciOpo-=aWhG3RkGw|g#iibyyEKT2YNmFYR=qoOOYA>LS^Bzs zKCg=!$>-hpPBY8T6<rP*phdj4MthlY=J)RrJ<M<xh}Zl$*e|JMf{p;m8ix5hOmKgU zpP_O4|BYuTX}6DU)N8j7*6n(}3Rea<7pk4ZPUrAOd>bd8;_fH7+dhzdH1+6=jk~LO y+`;2DUpJn@HN@tB{K$81hnGUJBe&1lC(hZ?iE4DhiB4?rwLlm{jNY8QhyDvb{#*h8 literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/controllers/getReviews.py b/Product_MicroService_Group3/app/controllers/getReviews.py new file mode 100644 index 00000000..87f4f38a --- /dev/null +++ b/Product_MicroService_Group3/app/controllers/getReviews.py @@ -0,0 +1,44 @@ +from flask import Blueprint, jsonify, request, json, session +from models.getReviews import get_reviews + +from kafka import KafkaProducer + + +get_review_bp = Blueprint("getReview",__name__) + +@get_review_bp.route("/product/getReview", methods=["POST"]) +def get_review(): + + user_id = session.get("user_id") + + if user_id: + if request.method == 'POST': + + #data = request.get_json() + #review = data.get("review") + + get_reviews_by_user = get_reviews(user_id) + + send_review_message(get_reviews_by_user) + + return({"reviews" : get_reviews_by_user}) + + else: + return {"error" : "null"} + + else: + return {"error" : "You need to be logged in to add a review"} + + +producer = KafkaProducer(bootstrap_servers = "localhost:9092") + +def send_review_message(reviews): + metadata =producer.send("customer_reviews", json.dumps(reviews).encode("utf_8")) + try: + record_metadata = metadata.get(timeout=10) + print("Message sent successfully!") + print("Topic:", record_metadata.topic) + print("Partition:", record_metadata.partition) + print("Offset:", record_metadata.offset) + except Exception as e: + print("Failed to send message:", e) \ No newline at end of file diff --git a/Product_MicroService_Group3/app/events/__init__.py b/Product_MicroService_Group3/app/events/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Product_MicroService_Group3/app/index.py b/Product_MicroService_Group3/app/index.py index 9f0267b5..79afca3d 100644 --- a/Product_MicroService_Group3/app/index.py +++ b/Product_MicroService_Group3/app/index.py @@ -6,10 +6,12 @@ from flask import jsonify from config import DEBUG, SECRET_KEY, PORT import os import requests +import subscribers from controllers.getProductController import display_product_bp from controllers.addReviewController import add_review_bp from controllers.productHomeController import product_home_bp +from controllers.getReviews import get_review_bp @@ -24,6 +26,9 @@ app.secret_key = SECRET_KEY # Read user microservice URL from environment variable USER_MICROSERVICE_URL = os.getenv('USER_MICROSERVICE_URL', 'http://127.0.0.1:5000') + +#subscribers.consume_username_updated_event() + @app.route('/product', methods=['POST']) def get_session_id(): session_id = session.get('user_id') @@ -43,8 +48,14 @@ def index(): app.register_blueprint(display_product_bp) app.register_blueprint(add_review_bp) app.register_blueprint(product_home_bp) +app.register_blueprint(get_review_bp) + + if __name__ == '__main__': + + subscribers.start_kafka_consumer() + app.run(debug=DEBUG, port=PORT) \ No newline at end of file diff --git a/Product_MicroService_Group3/app/models/__pycache__/getReviews.cpython-311.pyc b/Product_MicroService_Group3/app/models/__pycache__/getReviews.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ccf1bdd0dc2a3f16681b83ed686dd3e96875123 GIT binary patch literal 2521 zcmd58O>YxNbavNkZ-SlFhNOIFl~4&wky9GcL*&p>+q4u25JM@^R>s+#goX94nO!?^ zYFDV`;36bSRVfErDTj(u@dr5c1RQ$kVS_ATt<(ys>LItSQlyAe->mHzCq01FN*&LP z-`Bj4dGC$=LnzdZV4NOAGhg@+`kf-J!8U=_VE`79f)qwWQ}mnFm>fIBG8E=CF6W!_ z0qnbmrg()(qbR>Zk4{7xCveF$bakc#V7F}OI+m@BGA%Pr)%1&p#lc$r4Gb=#E@ZvH zy#tJUuo|Pnl$oU$xGg$D8|2tBs&EQZ@s-)7Rv2wzfXcoycLzB4*0~G<S?b58u|YSl zu-8zTPj0m7FZ;_Z*#=tRA~%mtEntlyeGtt{$)-^n4I#@*RYUV7f6Kx?M2=MgR&NVO zkdkuXHu{de12=VV{k9l%9@13_d=_{`FZ*BCO9i}aENW$rv0iKY^bcP8{vTe>p?U5+ znq!6_|Nl+)=1|K<l%H6@>D2L5;*6Lmn3j>l<Y;nOJZoa2XLER1oWw;H&kc(tYpMF| zuy~3XN<p@cCdDI@Cr^mVv=M8Fn1^*`(i1Ypb04H8Q!gkS7vJgVFah$g71rt$Y>Q|X zmC+~rX)h^g$9jqYV>&Rl1LHa{UmH{SZ~0s7jVQFepU`evp(VHCLA0G#XoW|4r@I}n zBeVi`{EcWFe<NV0Ydzo}QIvJq*qaVVj5(946UFCu6JruRYf9N%NxmqZ)NzuiMJy!^ zxsb!UWlE=jYv@@`I;#VNn5tD0jTtdrAOx4Bgi#<S7S9>vvUFG}W_1}WV&Y;})382^ zO;Odwb9h=jgXN35p&7F(291pzWKO6uG18b6RT*dACq^MZDrNI|DQ75HGo@K<HB%GI zm!5aWHPy6aBbPt4FaWF!@iJ@1;+i36HS-VvErC7=&ioj*tH?!Y`y{(zPq0VWCG+lq z?~C_G?_c@p?Vr>3>B(O{vM<QCf@>FM>|)7Y__S6m+uJKJH=G82tDqY#>`i8^>~t2w z$AlP!#@cplOkCK1R>$*sc%k7+8WM&q7YJY*B%@t~Ce`r+*EEO|!1GuxSlAI}uqD&W zba+`aOzimcB?F#&hfh(94xcBgZaH14c^T&|)zG7Y<5R$^^&bbIk$$Q>P=GXNRK*E3 zFD`SXfJw;-G*KtmqI>5VY|<(hn}g7Dceb>{Gszo33BWR4s86_PpU4mV(Km2Q`bMgD z*TcJ>ga;po2baV9YT<oV|I<i+HQ@Tuj(6E=s4n!}?780aRb^>*S%}qym@UNWk?o5k zUym$DhH8-^5cPHB?L+o-Gl_qC3H{64t3fx2!h76)6pXlt>DpBfMs6Oze*DXc8xz%u z`j$RQ9H<BTp9FV54(?tK?yUv)+TL_I;H*7+9ZueeyNKntwYOh|klpjv-7B!cToy)a z!l*5b)_b>BE&6eLUfmv8^-Ovmt-*NKi-O?aX2bFOVY?>|b6FU#3FEdf-Zt$27Yw_- zV3T^_cE7r|#<i`jnQ_Sc=ZE*a7eWt0y~#1|!R|<6kb4mGCCAaj!4Oa$jzp3Nxkn78 zJUYk&<<S^N;qj5wFb8kjPFhm@jFvSo6Z)_@I~$E3qXkIYD%1RfLu;7!hgWih{s<D< z;a*KX7vgZLpy5MgKhWq?X&!?O9A%iND0J2P)X@&RbJo!TyK}n!L1w^3n>Wwc-?ao| A0RR91 literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/models/__pycache__/updateUsername.cpython-311.pyc b/Product_MicroService_Group3/app/models/__pycache__/updateUsername.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d55720a3e7872e81ac56a1facc02ba57c682325d GIT binary patch literal 2407 zcmcf@TWH%>^vbgA>%_6+WNqd;50eBkcWJ`dMnl(TIElB8by;Z=vIap=q?=T&EO}Q_ z5(j6Lv5%}2x<R3XG3Zyj(S7uD-%a{Ckb@ycFer?D>`xF1re8bPj-5w47%koL)zNw1 zbIyIp_gh+;5Ww%J(c+FDp+6Z@2j3pCI|#%bq#%XUP?nqHI7a(4-<%KLyvAq!bAFKd zzd>_?;+sM#;cw=e;@sd>)6mt${3Os#vZ3olw&s-uncEA^UIIKkJiB9n@1PK}4ruRz z;sHE0Smz4d-2>XX9HAq2z5*m0Z>ZOK;C%;pzrwEz1>fCzi499e6oi7mz%Tmlf%ZYe zf<rJj%kw!nJU45EBB)%!N8f-MpsCNpQI7&gk3sbRWIKhXP#?0Y%T|kgHBg_SA5m#N zU`6XZLQ0?z_!0f&y9Zr+(CA#X7QAn@PaVxn2`X6SWZz|2^7X)1f!A48ZH5)jYTM7} z1r>!}xuT~3yP_4e%3nq+TpxN}{aZoxIa1A&ZqPOfomUk%tdo^_#^_R(tbH+aaUwmP zNh%A*&?U00k`*(pE0-io)tAhsB*0W=y834H%%0o1<cC$+?D@>4OhY?vo0gF!^pgqD zyTL3mO=*d&b=AF+c21Ejq9jdQmO;5_Yg&G-Z$h%91<52yLa9NMs=jB}Nb*e56*5e> z7CCIYc4|f^t2wwpAZX3okY$?!_o66ktw+sMO_UulHvmqiLERu(C9-W15E$94YPo`} z878o~ya87f4KZUOM^)W&F*P)8L6Wbzq0FjGa+Yf7si5nJ5~aq)1~STyC1vN)#r3wk zv05vtCC-0o6PkB9Vg|v8wHe^quj6M#);Lp?vU&N6__<CdsJcwV2}8ECM7K=wB4`a= z(!?1Z6x39$e9~A<PT7=_yf|(^O(Z#M&}(8^S(bDe+A@Ac(lnwk5tDUjmMkQviF`#j zG-F965Rn>+4cGB!s!WY3LYGyU%zsP`JNK?A<#J-yP>5!VwdCu|I+V-1(F66ceMR4d zQdl|W3Ain<BhNn|^!#<K=X>$CxY1OOC3a%H+p*qatiKfN-v~TuJN{k%_V7lq+}`m+ zq|`pJfxUpgEAHU97e=Azt;mgt)A82NBM)btljn+fw1h_;JnCT-YTv=}Z5%J+L<uJx zoOse2cRD|CqG!Es6mIhn7fO`FZMQDmxbW@d&B=|)a`Q1J>?wzj?}R(I!=1%&cPZTM zRENidrt&lao;S~Wh!+O;(I2?QiJX3z1_YysM@o3a!6Rkdwu2MfI8nr1CEVrUu5xRK zbK;~EecQo@hS&PC2~{eUr!f?U#Cc(8A5}9-|0X#RNGe^#V<kN1;IV(nXwZqCa`2(y z1zsT|F9yj#W))bWmuz&UVxEUR@^!jztQ|dSk7fq>N4=@>QGT<T19~&;&kUo@(H5Y$ znp2qpe(OCZ-+G_P9}fsXKOW>6Jv{tTH=hc)!lEXb*C_iY(+D8<L~Y9su~W$|nfbkc z9PD7SqhH;qzo1<p5$yo<44(xTTO*^i3t0AjG(QCdTZ7}Cpty5*lu^s|>aUF6aSjhJ Qkm7ng_{(z?(N2i>4^pN<3IG5A literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/models/getReviews.py b/Product_MicroService_Group3/app/models/getReviews.py new file mode 100644 index 00000000..ce8811ec --- /dev/null +++ b/Product_MicroService_Group3/app/models/getReviews.py @@ -0,0 +1,42 @@ +#from app import db +import pyodbc +from flask import jsonify +from models.database_connection import connect_db + +#Function to get user info +def get_reviews(data): + + try: #error handling + + connection = connect_db() + cursor = connection.cursor() + + user_id = data + + #Get reviews from database + reviews_query = "SELECT CustomerID, Username, Review, rating, ProductID FROM dbo.ReviewsAndRatings WHERE CustomerID= ?" + cursor.execute(reviews_query, user_id) + reviews = cursor.fetchall() + + reviews_data = [{"CustomerID": row[0], "Username": row[1], "Review": row[2], "rating" : row[3], "ProductID" : row[4]} for row in reviews] + + + + #connection.close() + + return (reviews_data) + + except pyodbc.Error as e: #error handling + print(f"Database error in get_review: {e}") + return None + + except Exception as e: #error handling + print(f"Unexpected error occured in get_review: {e}") + return None + + finally: + if cursor: + cursor.close() + if connection: + connection.close() + \ No newline at end of file diff --git a/Product_MicroService_Group3/app/models/updateUsername.py b/Product_MicroService_Group3/app/models/updateUsername.py new file mode 100644 index 00000000..d673f8bc --- /dev/null +++ b/Product_MicroService_Group3/app/models/updateUsername.py @@ -0,0 +1,48 @@ +#from app import db +from flask import jsonify +import pyodbc +from models.database_connection import connect_db + + +def update_username(data): + + try: #error handling + + connection = connect_db() + cursor = connection.cursor() + + user_id = data["user_id"] + username = data["new_username"] + + #insert data into user table + update_user_query = '''UPDATE dbo.ReviewsAndRatings + SET + Username= ? + WHERE + CustomerID= ?''' + + cursor.execute(update_user_query, (username, user_id)) + + + #commit changes to database if no errors + connection.commit() + + return {"message" : "Username updated successfully"} + + + + except pyodbc.Error as e: #more error handling + print(f"Database error in update_username: {e}") + connection.rollback() + return {"Error" : "Database error"} + + except Exception as e: #more error handling + print(f"Unexpected error occured in update_username: {e}") + connection.rollback() + return {"Error" : "Unexpected error"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() \ No newline at end of file diff --git a/Product_MicroService_Group3/app/subscribers/__init__.py b/Product_MicroService_Group3/app/subscribers/__init__.py new file mode 100644 index 00000000..377b8371 --- /dev/null +++ b/Product_MicroService_Group3/app/subscribers/__init__.py @@ -0,0 +1,5 @@ +print("Subscribers package initialized") + +from subscribers.updateUsernameSubscriber import consume_username_updated_event + +from subscribers.updateUsernameSubscriber import start_kafka_consumer \ No newline at end of file diff --git a/Product_MicroService_Group3/app/subscribers/__pycache__/__init__.cpython-311.pyc b/Product_MicroService_Group3/app/subscribers/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3983da2bfc76957fedcc9a12c59acbeee1d68af6 GIT binary patch literal 523 zcmZuuKTAU~5YOvtMHDw@eS=`TxacGzN-IwOfm#X@2x)R{Ltm4}C9hB?zlGmG5x<5X zpn`*RDmb|b-JDFcQU#C8<rnVmcXzqFm6avp<#c(W{pj!4@c5B<2Bte6+>inRBFSw; z$b&!M5)m26LK^i8mxV7JdmLZJ9vADRQo35N=PfHxwE%6Bana))NR(Di@l;)bd<#64 zXuKwjws{{|ZUHq9Ad}pIWH12je8j4C93AWNc8{}JG@e$9<5Gr7yYYsdSK9hcZp^sm zJz$s#i{9LmX(;{iP~D{=&QjhViY`6VP(w8US~J4;qn)Ma-fJ{ZX+wJlTIGg`X(#m@ z5r(vCa<q^%4fg1v9B?f_Ce<!aQ_vl-e%Pc5t>gkkSDVyy6nI87G8c}WD1oL9I8XxE zF`7Kvraa5&uTdyt;ky{y%7!0{dwrjn!ajzrg)P_vZ{Fi5ie5<Rx-?qYd?Mv%QXY}= Rgq)53>VzDP{!?7^B%dxfrRo3x literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/subscribers/__pycache__/updateUsernameSubscriber.cpython-311.pyc b/Product_MicroService_Group3/app/subscribers/__pycache__/updateUsernameSubscriber.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecca0f3a049b16bf2c1abebacb308cdcb80d4cc0 GIT binary patch literal 2125 zcmc&!&1>976d&!5wAy%`wd=%=y-uno*kljh(7H6C^drGenqb!{{%By?M99+YTDCrx z8Lh#_1|M=rp~pgdNFgVO;2e7I-%!v7l^DT-p{GI*hTMGWn^|k^tqVPNBt5;EH}gK` zz4v?B+j|bdc$rhG@5u=L!6(T`9W(Fdf%y?x$dVl7N@Ypne9B3=>2g}|X$QM<Sr$BY z6gN}O2wry7vI=`;CtJ>1%2QN6XJvr)Sn>iYs(*3=MJeu`F{*3El<%>IODHVlX71dZ zxuY-Ko&WakJk0Zrx@81JZ!khV!zHk!EUr*uSaasFlj4Vgrr~>6mbk|O&}6K3_#jz= z|7sE=#P&M13$wk>iqw6c>lMRF?}Dzqjy~9zO=JjJI1o45UU@Bd>)b|LXc|3!ye(}> zt4ea}MJC}+|1G84&UPy3KasC?Y;L9gu`eB5JlSVux~1UlDe2bPScXo{o|S(8#6moC zb4SIo>jpCe8<N4a32p4UL)M8SlGC2MgfXKA(pRZi7Q$Gm`qVXo&1>yc+g?peGOD#R zY-ymy3reL@e6ddbs_j71MeZ#<@awh-neSir{eT73sOwM;>x8mRxe-(+Zf#~CXojn; z5K4-<IOF)W8kmTCmJMc`V6tl0V*Ft4-oqH%9=O6YN_ok|^19(PNUT`I^eqzORpxu( zv~O4}mh05^0t(H6ia1uy<0_3a#{tHDiK9@Wh7OL!xzj6*ThL$}{W|q&WeHqn6~o;y zS1J!ZGEMDuQknKmD10wqm2W`mdxle4@<2eD9c*ZRRa<CKN;WD}euFZiJ@V;V<&L#( zcqXy5sTIR<h*u*_vpww*S=JVbx#IZ{zD+<Q^{s{(=wI6=^%vm2Y?J6;QNK~2tQhrr zg*BF$N$q9sR{N&8i#(4D9Z9La5nnkDywii7yoij^QHb(9d~6TM4r<|^2oL>Sd+vmj zPeQCWu^wR^7!W+24f{W7;+qk^8RDC*{AhUj<KJ>&eyN#Xit<Z4_xA@1he(#k1$ma) zFI;{8`P;&cH-#I&WSWIrQQ=moUTO^$e%K7Je$*VAjD{wk<yva*v$du=5~(AhI>Kj8 zQ!PYlAyf-3b?B#DQyq)cu~58+J&F2v;4b=i5cvxv{}+gyY1$s{XL|&>ghL1brVEU= zk)>=Qy#pv)=!JT+`-IyCmS?IxI9NklXXYs1OgXe{jw}QQ4S0_Vbk>r>hu+*AzE2#- z*Q(TawKb029Vtg<I9DUVVlhj3LC`!WeVlOkqJx}p=o2LaJ!cS?cN^p8;CN0b)B^$U zjH9eZ3qa!wVu#)qC*II&AR2~`IY9oq?k1YJ6yZ{cOD&uY&y6+lc!bA8Jl+}@{{4e5 z!-3n)f!oo*?VZ{Ekt;j1P{aGU?=2pDg9n@VQiLys$xAPTLBJVVI3&O%R=_PlnKr0g zbOB2oR_g950VHv@9Uk0n`zkJguJJ`zE_Lc)TG{Yd=`lr<dk1ucS{UkdvU$YENN zq<!>$*!>=KPeFQsJ`B6x12h_TzlREvayvcz*+=Jh#B-=*C1}GA8C0a<Lv)r1SN{f? CLIptp literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py b/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py new file mode 100644 index 00000000..4235a17f --- /dev/null +++ b/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py @@ -0,0 +1,34 @@ +from kafka import KafkaConsumer + +from config import KAFKA_SERVER + +from models.updateUsername import update_username + +from threading import Thread + + +import json +import logging + +#This function is called in the "__init__.py" file in the "subscribers" folder +def consume_username_updated_event(): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logging.info("Consuming username updated event...") + consumer = KafkaConsumer("profile_updated_topic", bootstrap_servers=KAFKA_SERVER) + for message in consumer: + profile_data_str = message.value.decode("utf-8") + profile_data = json.loads(profile_data_str) + print("I am here") + print(profile_data) + update_username(profile_data) + +def start_kafka_consumer(): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logging.info("Starting Kafka consumer...") + print("Hello from kafka consumer") + kafka_thread = Thread(target=consume_username_updated_event) + kafka_thread.daemon = True # Daemonize the thread so it will be automatically killed when the main thread exits + kafka_thread.start() + +# Call the start_kafka_consumer function to start the Kafka consumer thread + \ No newline at end of file diff --git a/User_MicroService_Group3/app/__pycache__/config.cpython-311.pyc b/User_MicroService_Group3/app/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..105819a92eef07108a2fb4558af6e0b1ad972654 GIT binary patch literal 348 zcmXv|!AiqG5Z$C{wJkY`7f%bGdhy~-M5t+~AllL-6vIM^*=f6&?uOl_kXw%af#45_ ze^hc3Jb5ehRy??=`i7Z#!<%8=n{Bs{MsV{DUEM#c;UDH7*`8?ff+(U!f<i>i(4e)@ zq*hp?hKD-!uWIq$FB^R+vh<uiA0gDSN>iw^-gB>me%bO|XXN^mTlb-~hJ%s+j<(g& z?$x;<fdZ*Ww8-N*8F1)HwgS=<akc=yRAi`C!J~u(TnkdMWsb!ZdzqAw6GvoH0Uita zM7nep@fav}=24OWpMk=R<1sv9AL2O|iI_1^`-hV|7E9rQT(KA?zs5<FrX&`8%4TP2 wzB{~J2%05uCEMDnp;MjevZ)z{u|~~eADaeh+C_bB9~Z5UgLYw6A)9*d2j&N7WB>pF literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/config.py b/User_MicroService_Group3/app/config.py index e69de29b..358b5ce9 100644 --- a/User_MicroService_Group3/app/config.py +++ b/User_MicroService_Group3/app/config.py @@ -0,0 +1,7 @@ +import os + + +DEBUG = True +SECRET_KEY = "Group3" + +PORT = 5000 \ No newline at end of file diff --git a/User_MicroService_Group3/app/controllers/__pycache__/changePasswordController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/changePasswordController.cpython-311.pyc index f2bccc2cdba24cef3aa5a38361740cb00752099f..34cc426ee500d1191ecb52b66c1c4517c902dad9 100644 GIT binary patch delta 170 zcmZ20w_c8KIWI340}yC({YwoJ+{kx@U5N+CExyahz|g?(m5qU4tS5Vh=0!f0D|{*q z?hn}cJ~FsXX5pB{C^C6I$23Nc$!47Lj3S%EIKMD5#%=cIW@BQ^-yFot#>jULXwC;_ zMn=XD91M)+lMDDnC)e|_0dcyv7bBy=2L=%Nk(q(XmGKIr%LgW~U=kBABijcCIH5FI HkY5G>xa}(e delta 190 zcmZ24w^ojCIWI340}!z7_?7yAe<R-&b|p?AxA-n2149GDS2hNIv7YQ1niu(0uJEZe zxIbX$`^exrnT2B(quAv69Mc%tCYy1}GYV}E<NU(N7`54(n~jMvYjY4U8za{lpgA9y z85tRGOfKLPpIpbsIk|-|#od#U(cl9Ei2TURz~st!h0)~$6Id{TiI<V>0|T5;;AS-Y Mz<@~<839cO05bqEp#T5? diff --git a/User_MicroService_Group3/app/controllers/__pycache__/deleteProfileController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/deleteProfileController.cpython-311.pyc index 8e06212bf94edd278c153db45bf9c8cb26a0fc10..6ce448acfcb8142341af9ce1dbd5583428925b08 100644 GIT binary patch delta 106 zcmcb>b%~32IWI340}$AA{7c=pk++MPmlMb<o(Uux7`}3BUcxNR$kzqrePCu}Wc<Lv uz-T`CB8&9o2P|xp->}%LN;4XKU;q*ynHiWI8Lu!pd|-kJfyIj?fO-L+ZW<8) delta 102 zcmcb_b%Bd_IWI340}%M`_?7Chk++MPmkr1(o(Uux7{0P?UcxNR$khSlePCu}WV|u? qB8%+g`z&me-?7-MN--LIU;q*ynHiWI8Lu!pd|-kJfyIj?fcgM%i5c(! diff --git a/User_MicroService_Group3/app/controllers/__pycache__/fetchUsernameController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/fetchUsernameController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..993fb4379d90d57d8dccc87743e0bec879754e00 GIT binary patch literal 1293 zcma)5&1>976ra(z<2dTtj<Y#5mQ!O`XzW9hO9)9?8`2c=0UMLD2!x`U^~%=AW+W|a za6%3__z+543f`knZi{>Ht^Y!g+OSYFr$A{TIk}iza!KFF-gVcfKBT9a-|x-Ld%rjO zX>9Bi0{iUlNBT}e=ua`}n{qTb*nq(%B8cDsg}8=8sV0STO%9cs5~?*73r-5OP_OA2 zNr+-1Q)3(U+kyAcY9n-Ht2nEV^uI(Q>I(i<8;&RXOSBCkJN+<J8zn{+RYu+lq@wbX zFN2IWnIENGUrpl3ueZ6*=#z{lDOUu-^@JvgA4e6;Pp{C_$r8#UH>7+NX3IyDr=<mf zFZ>7M%7gpWhp<WyY1)WM;tjHZfzU;U_uy}En<&NbIkMHknBZ*~?+oV8P}<iMVpqlb z!icn1XvDrw)jkINAa+=TXLucN4fZ^aM~KKL&Xdy7V}4ya!OH2_F-w$n**}plQR`9_ z5sm0R2GxywTo)=iK4GGZT=EGw`g*?oT|g>jEM{DZvLLAFOc$68sxna+*AAuRhG>N7 z4l@8|qR@)ML^fO@Zt8MP?0RR3nE)k%w!l98ws_561|qTDu<bSM`w?AYev8^mv6qE3 zN)!75uyN!D_HqOSOZ>EL#dWKiF-F_=Vw|yrT90D3W`99iZsbv7EjHXBpwS9VEI+ay z(Z|+9>NTP`h*x}?6bCwYeUHUe%38iho!czVnwM?2*|fblN?8ocA*VV`y@p6n+^)p| zG2d(#WfV>m^<>~)p!XUwr(UgfD%~@)y)&~fZofB>VZMCcnR=~H=lV48pPcKN(_M3> zXU=RWd!@6R<sZtO+3zp>cws|>=!xl0t2;i|8=u=S{xYXJr?$Sy&&_wug`T;vJCU1L za^uRrhDznmTyD<f#>@d6jP6xVbG070$r=+Eun@oK4im{8c5E_?2@R6@p^}PTal>&$ zeU8IR1v~hkoX1VBf-)&BD*Xkq^J2d;xDUp4*f0y|4Q9bq+}-3`aQiaGcn@9A|KGER zF6G0|o5@eVyVD7O{;E59wKsV+N2ND-{104yjm!D@&v#q9jU1P|_+}5^+?OWs#eD?s P9~nuv@DNnsMZW(6i7rTP literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/controllers/__pycache__/loginController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/loginController.cpython-311.pyc index 0ae33a0fab843db2a609b147bf8a5d6eaea25f24..c0b17d9c4604c96ba994a28b64fd1eebc7061a71 100644 GIT binary patch delta 66 zcmca7^+1YmIWI340}xE$_?IfjyOFPsjge<_FB>Z}qtoKaoJ@>Clc#Wh=Dz?`@qw9< Vk?{i?1Ecwc$rE`LCU4<c1prbS6086K delta 65 zcmaDLbx(?KIWI340}zxQ`H{MrXCq%78za}|UN%-{Mu)|dIhhy(CQsr1%ykZ^;sY}y SBjb(9^LfN4Z{T4A;tc?SYZL_l diff --git a/User_MicroService_Group3/app/controllers/__pycache__/logoutController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/logoutController.cpython-311.pyc index fef5e24b0dc447c671daa0656ba2d91c90e66b0a..63d12e36ae470889c341e2c26608db4c1b994b39 100644 GIT binary patch delta 53 zcmX@Xahii~IWI340}$-y_?H^Zw2|*F6C=muH%wRg8-ao!m>C%vKd><{x-(9`z^pa- HJ98iak@F8Q delta 48 zcmX@jae{+yIWI340}#ZV`;q#CaU<VdCPuc&Z<wxf)d2-RFf%eT-k5xmS!ePu=0E^* CeGkF_ diff --git a/User_MicroService_Group3/app/controllers/__pycache__/showReviewsController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/showReviewsController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e94a298c93ec474867d52280eef3e0341f88aca2 GIT binary patch literal 2018 zcmah}-ER{|5Z}EIf8cK?GR1%}HG~?8q@k#M6p(1Bf>aSu!$;-1Ivw7%bMg7k-8&~r z>PS|F)U=9P9xCBVJmdjUD*C_+Z~Y_AktM8^kRnw)@a78jg{RJ4uw&DQPR=u%nc3Ny zo!{(lk;ond^y)Awz2`^hFZZ85NpBagH(_xf5k#<#syL6ULSCqfd9f<xCG6@2U9S4_ zK5s4R{=8p66cdRC9tj9Nf!_}0gG44i;wOOzVtx;akv(^DK173?;l9VPBq0(m<3A#! zF-Y_-dIWAy2Cn%C5$91Z{>s(lBp&=!uhSaS44eBGEz{6SE8NfMH+5=(#-f&`nMMxt z$meRQqRyCxRj*Pu$3xbFx%>rP(&)0a8r99BsxO$9eeUdsXHW8^YgE{dRVg#GUgH6( zGF^kHIguysn5J#nOsy#vWlNM<Jm7gL8sQ1GZkvi(Dp}Nq7{Fg)$hGLQKFP2U;rBWU z+WW{JvJp{3_TUl`dWe6*Yq*Toga*EhzRs_S4RLW`-*lt=hlub9B0d>JU6btKuG6A> zx<?J^9Y47tZ2J1vVcC#JJu$LlyY|LA=QU8pJA(-r8F=HX2Hp(pdhf1ATZ>UcfYwTL zJYK9@wh4Xe_h417+ocm{a+t+ocP_{Py@*GOZ`-NBqQvDT6|lg4gceOgx#Yru%etu& zi~H1CjT(fDIt5)(H!Yg;@sLrk_K)C!el!<99xk}Q3iwgWl*e{73Q=uUfyVRDkiv3r zEaTCeXEWytHvtn?L9MP77Yf%5dYNfUv~bxh0`LsmDqIJvX{dVPrU3?KY4%FSEM?~F zjM0_Cj9F(E&D=IwrErNXsYa2K%*=wSL*iv>Wi%smo8HOXpv48l)Xg#=(mPPOsuh_z z4`|eiRGD=l`%wXkE<jZ_GhsXAG=%w?fqJsG!eei1?_UPXKuK<ctzUsP(TmstCw2+G zXBT#4^GY`wZ_f67X#7AAh2^Bj*8SV*!w*h8Pfu>8Cm%1j)2BP>)9bN+d}#0fUlunH zwNulb)bx4?wguxqM}Lgo`?ej(b^=)^kOil3Y<>BM^Bd<|pKOIDoX|u!oLK*?C!+AN zUI59F@8`aoYfIxDY21;<w?oP1+-pb<ttO`GaN|=$#c}ESwfP$`_0T|j!6a7Eb?lQn zGT!jDU@<y;i-VCNcogt!sDaqD-G3!v=i*@Wh*0qck{ui#vr%xbVLQ}M0HMY^(dQ8n ziKJnW@MgL)=bz(#w=Q^6*!!@P9RS89qps^*ri__vHR&QPW0-aZfKUdUXhzP*Tr_gA zOl{`QAouNDf!9&yrk@koQ4nlDFw4z5lVOKI@bK`f$Bu*Q1J~tCU`+(=iKR9wtz0{L zq!T^ToZa?EdnhPRy$B^YF1BuMg|bd4`!aR3ojTS@9b2D$IhJmnZjWU<V_7Gh-5x*K zT5`rFobbeUe6O?bgcF-|0+Z}81c#}Px+2QulCD}6=3cCqs#n2IL2|`?zrDF<<6!3j zMKRPWRTLf@&Re-tV+nVE#&wcm4s7bx@;mYl^GbaaIA1kMU8fh>G`P7<xBdjy6EVhJ z^s)1QUl$#6M!zl!HNC&><o<iP*44*n+R0O$<fu$w;KjUVam%l7<ILg*o2%}6hr y!ec!&%1$C7@f@eNaLU<x{OPTyR~(#b;|m>pp(jM}R1X3BTSUUe5sjzzs{0p0LjlzQ literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/controllers/__pycache__/signupController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/signupController.cpython-311.pyc index d6315f975befa50cae416644dbce66638592358c..55cd6b76556ac83d7c5d814dc2a64f828492b907 100644 GIT binary patch delta 192 zcmdlfvPgt?IWI340}$wP{!86Ikyny&)<ktn8778Q#uS!R&Sgvt46A_{0;0H5xfXCw zPGl0DI8%e2Cxx?xA&Ph7iBM)X*3_b+{G!dOEGroqxi+6?Rc92HxgckHLD=j9kJ$qr z;R$IMxMeS}$ZqClZ(?M$n%u{c&&W6VABWXsJ5C#M6QJ>oKwP{GNPJ*sWMurn#=vMY kxu4T@@?B0XVYv?s+Kh4^nHiY$t}yC;U;=U`OL55q0M#Nd-T(jq delta 243 zcmZ1^vQvb2IWI340}y!Fd`r!k$ScXXXrj8MN(w^?a}H+|Clf;|V+u<u*D@vshSfj} z0a4tk+zWUnZ)6mmI8lS0H-)o>A&PI~fly`+_T1Fs;>7gS&C)C@85ub@A7xc%6qUQ6 zV17Z^;sTGw10K;CY!|rYFR;jOW@K+-WVD>z!jaF&KluxX6)Q_dZesFeT~1q3Q=m1B zKwP{QNPJ*sWMsU-U_7~z)0OiE19t-$PCmw|Wu)+dL7P$GBQpb&-W5jO4@^MLhd4%F OMz#+Om_(5Z&@cd@b2~u* diff --git a/User_MicroService_Group3/app/controllers/__pycache__/updateProfileController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/updateProfileController.cpython-311.pyc index d12100ee3869119656505afbb8d537567f89b91e..8b7bc1569e5e102cdf2927d1001d7ef46f330135 100644 GIT binary patch delta 1107 zcmZ`%O-vI(6rS1sY`g7lf3O8iB&$?#tpPNIXb~e3Fc?FSS`HP{)a(|U{*l=&Cbd`& z95`qK?u8f*oT>&6B$~*PgHhwfk~Gn5Lc&20CLT(n7f#M>e?m>1y!qanZ@!)P=IwlT zJZs@zvMdAe_|gwzZ|PO84Q{P=Unz({G$ySnCd@#9V^h+WvWM*uP(XsBSz?P60GoJL zN0^hi4M%--+>5kmnT1={X1&NPfg+Y|Hl$&vXbS?t{*y3*Y4zj8fB-dTc20~ck{HR# z5=uu?66QMQvJaAR`C)^L)J4*~lvY#^9D+~OAnY}+K-8%&!7Tj#<_LPBdfDJASVe2z zIuFpTJjh!_V|$|jky)n}7^S5_fPWRuS6Hwqo?}|32=R6BtPThiYdr=aZ>{ILUM2C- zHqo|jZ2l;SJB_DZWaCix9Pxr<LZiw3BXJS2>at;=;KZjO7Xdc`QZqV1fK;T>DM^;2 zvywm|BGl|@=~1Iuf-%R2^rrGbC8}g)%@V5hHb;|)A0NrFqok93?HtV{A(TOyF`Z2& zbMBC={xXafEF>R!Imm`Vuvc?gtA(ax8O@0QT=f4{R+YNOPO4<|zZW5d##ZB6ewpm^ z$HvjS8v(Uw{Lpn4Z;(w{!Hr)8f6Tz)eVSMk_Bdae^DW*ypt(cPtv)yH6x_gjdZT^M z<1c&s%VP(QwzaX6;|#Wg^A~r=KPAf}_e!T`u&prreBXBKj<9>X9JsT`PnG$p6?Wg* z^D4LJ43wRLk~8q5wPV}68!t`Hl*jIu5~u>eP3kU%9UrRUApmXD)NdUz&$_0m3JaW_ zIAg`FJ~nqim-@myJlLvVRqoN<h!l&b<4Qb}mi5+ZCu?tALUK<c8cRect8X8#kxl(- zK6i<<;59&9*dZT=Bg@rPM$9IqYp545$%B;NW2hJ)gcUP@L+UW?Q7370ZTdSwf2rBN gfzeX4sX6+B&ky@50K=gHP=jR{s8DrAr}Y~C0{@>HP5=M^ delta 627 zcmeAbKE=<soR^o20SMf8{z_fNI+0I;amqw>%LFEdRK^sRRL*5g3=FG*7y_cWQn?mz z!+6Ma3Tp~mI^!C4RP`wwEey+m%2vabM)9O@1~X`KO}r60IhoOxQDyQ%Mt!ED?~|`E zmNM?x?8PL;Sf9lSQ(nWdj1j0Ch#{bsvqTieW?;aO<tl;e1j=&NFrd07m?4ETg)5U0 zOml;1O&-5n?4`x2Me&&_MIe9OVolARY|f%D%Ln8X@q-8f5FrR6gg}HakeGahB`l2% z$hgItQkq*(T*LunYjPKXG~MEan3tE9e~Tq0u_O_vDNvOlHMjV(iu3d0!8*ZuKv7Z* za?s>itXI_(fDCq!h$Jv18W_H^G4PA^WY5sN$ft6JPo=^A0XyFZ2Gz+^*>)I;Fvuy* ziCV#VQP${+tWk#_P_3Ba0?CV_+E+xiJKUZMOU*D_V17|p`--sk1s?4WY?E)Y%Q5m! z{=x1zxq?GQ4`kI!h9X5ERU{82esS33=BJeAq}ml}0J)%;D4qu-J}@&fGTxZ{kV9nh j0}iXncAVNOnv4b?7=Xk_W(FqfD~whjm|!AcVX&D1pB;#s diff --git a/User_MicroService_Group3/app/controllers/changePasswordController.py b/User_MicroService_Group3/app/controllers/changePasswordController.py index 516ca01a..5fbb96db 100644 --- a/User_MicroService_Group3/app/controllers/changePasswordController.py +++ b/User_MicroService_Group3/app/controllers/changePasswordController.py @@ -1,3 +1,6 @@ +#This page allows users to change their password +# +# from flask import Blueprint, jsonify, request, session from models.changePassword import check_old_password, set_new_password import hashlib @@ -9,9 +12,9 @@ change_password_bp = Blueprint("change_password",__name__) @change_password_bp.route("/user/change_password", methods=["POST"]) def change_password(): - user_id = session.get("user_id") + user_id = session.get("user_id") #Get user ID from session - if user_id: + if user_id:#checks if user is logges in if request.method == 'POST': @@ -26,18 +29,17 @@ def change_password(): new_password_salt = new_encoded_password["salt"] new_password_iterations = new_encoded_password["iterations"] - + #collect old password, user id and email into json old_auth = { "user_id" : user_id, "email" : email, "password": old_password } - #user_old_auth = check_old_password(old_auth) #Collect user data from database + #user_old_auth = check_old_password(old_auth) - - + #send old password to database old_auth_info, value = check_old_password(old_auth) #function returns certain columns collected from database if value == 1: #if user exists in database @@ -47,12 +49,13 @@ def change_password(): old_password_iterations = old_auth_info.get("Iterations") - #password authentication + #password authentication. Calls password fucntions old_password_info = generate_password_hash(old_password) is_correct = verify_password(old_password_info, old_password, old_password_salt, old_password_iterations, old_password_hash) - if is_correct == True: + if is_correct == True:#if password is correct + #passes new password information to json new_auth = { "user_id" : user_id, "email" : email, @@ -62,6 +65,7 @@ def change_password(): "iterations": new_password_iterations } + #sends new password to database new_auth_info = set_new_password(new_auth) @@ -86,7 +90,7 @@ def change_password(): - +#password encoding def generate_password_hash(password): # Generate a 16-byte salt salt = secrets.token_bytes(16) @@ -103,6 +107,7 @@ def generate_password_hash(password): } +#password verification def verify_password(stored_password_info, submitted_password, salt, iterations, user_hash): # Convert the stored salt back to bytes salt = bytes.fromhex(salt) diff --git a/User_MicroService_Group3/app/controllers/deleteProfileController.py b/User_MicroService_Group3/app/controllers/deleteProfileController.py index c74dfe1f..f29f3689 100644 --- a/User_MicroService_Group3/app/controllers/deleteProfileController.py +++ b/User_MicroService_Group3/app/controllers/deleteProfileController.py @@ -1,3 +1,6 @@ +#This section allows a user to delete their profile +# + from flask import Blueprint, jsonify, request, session from models.deleteProfile import delete @@ -6,9 +9,10 @@ deleteProfile_bp = Blueprint("deleteProfile",__name__) @deleteProfile_bp.route("/user/deleteProfile", methods=["POST"]) def deleteProfile(): + #collects user id from session user_id = session.get("user_id") - if user_id: + if user_id:#checks if user is logged in if request.method == 'POST': @@ -21,7 +25,7 @@ def deleteProfile(): "user_id" : user_id } - user = delete(user_info) #Collect user data from database + user = delete(user_info) #sends user data to database return jsonify(user, user_id) diff --git a/User_MicroService_Group3/app/controllers/fetchUsernameController.py b/User_MicroService_Group3/app/controllers/fetchUsernameController.py new file mode 100644 index 00000000..311efa0a --- /dev/null +++ b/User_MicroService_Group3/app/controllers/fetchUsernameController.py @@ -0,0 +1,28 @@ +from flask import Blueprint, jsonify, request, json, session +from models.fetchUsername import get_username + +fetch_username_bp = Blueprint("getUsername",__name__) + +@fetch_username_bp.route("/user/getUsername", methods=["POST"]) +def username(): + + user_id = session.get("user_id") #gets session data + + #if user_id: #if user is logged in + + if request.method == 'POST': + + #User data from front end + data = request.get_json() + userID = data.get("id") + + + + username= get_username(userID) #Send user info to database + + return jsonify({"username" : username}), 200 + + else: + return {"error" : "null"} + #else: + # return {"error" : "User not logged in"} \ No newline at end of file diff --git a/User_MicroService_Group3/app/controllers/getUsersController.py b/User_MicroService_Group3/app/controllers/getUsersController.py new file mode 100644 index 00000000..8c51a05f --- /dev/null +++ b/User_MicroService_Group3/app/controllers/getUsersController.py @@ -0,0 +1,18 @@ +from flask import Blueprint, jsonify, request, json, session, redirect + +from models.getUsers import fetch_user_info + +from kafka import KafkaConsumer + +consumer = KafkaConsumer("review_events", bootstrap_servers='localhost:9092') + +def getusers(user_id): + + pass + + +for message in consumer: + + event_data = json.loads(message.value.decode()) + user_id = event_data['user_id'] + username = getusers(user_id) \ No newline at end of file diff --git a/User_MicroService_Group3/app/controllers/loginController.py b/User_MicroService_Group3/app/controllers/loginController.py index 31313b3f..232350cd 100644 --- a/User_MicroService_Group3/app/controllers/loginController.py +++ b/User_MicroService_Group3/app/controllers/loginController.py @@ -1,3 +1,5 @@ +#This section allows a user to log in + from flask import Blueprint, jsonify, request, session from models.login import fetch_user from models.login import fetch_password @@ -40,7 +42,7 @@ def login(): password_info = generate_password_hash(password) is_correct = verify_password(password_info, password, user_salt, user_iterations, user_hash) - if is_correct == True: + if is_correct == True: #if password is correct session["user_id"] = user.get("UserID") response_data = {"message":"Login Sucessful", "email": email, "session" : session["user_id"]} return jsonify(response_data) @@ -60,7 +62,7 @@ def login(): return {"message" : "null"} - +#password encryption def generate_password_hash(password): # Generate a 16-byte salt salt = secrets.token_bytes(16) @@ -76,7 +78,7 @@ def generate_password_hash(password): 'hash': hash.hex() } - +#password verification def verify_password(stored_password_info, submitted_password, salt, iterations, user_hash): # Convert the stored salt back to bytes salt = bytes.fromhex(salt) diff --git a/User_MicroService_Group3/app/controllers/logoutController.py b/User_MicroService_Group3/app/controllers/logoutController.py index c7ff97bc..241e00d3 100644 --- a/User_MicroService_Group3/app/controllers/logoutController.py +++ b/User_MicroService_Group3/app/controllers/logoutController.py @@ -1,3 +1,5 @@ +#This section allows a user to log out + from flask import Blueprint, jsonify, request, json, session, redirect @@ -6,13 +8,13 @@ logout_bp = Blueprint("logout",__name__) @logout_bp.route("/logout", methods=["POST"]) def logout(): - user_id = session.get("user_id") + user_id = session.get("user_id") #get session data - if user_id: + if user_id: #if user is logges in if request.method == 'POST': - session.pop("user_id", None) + session.pop("user_id", None) #deletes session return ({"message" : "Log out successful"}) else: diff --git a/User_MicroService_Group3/app/controllers/showReviewsController.py b/User_MicroService_Group3/app/controllers/showReviewsController.py new file mode 100644 index 00000000..8ac832b3 --- /dev/null +++ b/User_MicroService_Group3/app/controllers/showReviewsController.py @@ -0,0 +1,54 @@ +from flask import Blueprint, jsonify, request, session +from kafka import KafkaConsumer +import json + +show_reviews_bp = Blueprint("showReviews", __name__) + +# Kafka consumer configuration +consumer_conf = { + "bootstrap_servers": "localhost:9092", + "group_id": "show_reviews_group", # Specify a unique group ID for this consumer + "auto_offset_reset": "earliest" # Start consuming from the beginning of the topic +} + +# Function to consume reviews from Kafka +def consume_reviews(num_reviews=1): + consumer = KafkaConsumer("customer_reviews", **consumer_conf) + reviews = [] + + # Iterate over messages received by the consumer + for message in consumer: + # Decode the message from bytes to a string using UTF-8 encoding + review_data_str = message.value.decode("utf-8") + + # Parse the JSON-encoded message to extract the review data + review_data = json.loads(review_data_str) + + # Append the review data to the list of reviews + reviews.append(review_data) + + # Exit the loop after consuming the specified number of reviews + if len(reviews) >= num_reviews: + break + + # Close the consumer to release resources + consumer.close() + + return reviews + +# Route to show reviews for a user +@show_reviews_bp.route("/user/showReviews", methods=["POST"]) +def show_reviews(): + # Collect user id from session + user_id = session.get("user_id") + + if user_id: # Check if user is logged in + if request.method == 'POST': + # Call function to consume reviews + reviews = consume_reviews() + + return jsonify(reviews) + else: + return {"message": "null"} + else: + return {"error": "User not logged in"} diff --git a/User_MicroService_Group3/app/controllers/signupController.py b/User_MicroService_Group3/app/controllers/signupController.py index 3876e7a8..0ec06637 100644 --- a/User_MicroService_Group3/app/controllers/signupController.py +++ b/User_MicroService_Group3/app/controllers/signupController.py @@ -1,8 +1,9 @@ +#This section allows a user to create a profile + from flask import Blueprint, jsonify, request, json from models.signup import new_user import hashlib import secrets -import hmac signup_bp = Blueprint("signup",__name__) @@ -24,7 +25,7 @@ def signup(): salt = encoded_password["salt"] iterations = encoded_password["iterations"] - if email.strip() != "": + if email.strip() != "": #checks if email is not empty (email cannot be null) # Create a dictionary from user data user_data = { @@ -48,9 +49,9 @@ def signup(): return jsonify(update) else: - return {"message" : "email cannot be empty"} + return {"error" : "email cannot be empty"} - return {"message" : "null"} + return {"error" : "null"} #This function encrypts the user's password diff --git a/User_MicroService_Group3/app/controllers/updateProfileController.py b/User_MicroService_Group3/app/controllers/updateProfileController.py index faedd619..bca31198 100644 --- a/User_MicroService_Group3/app/controllers/updateProfileController.py +++ b/User_MicroService_Group3/app/controllers/updateProfileController.py @@ -1,15 +1,20 @@ +#This section allows a user to update their profile + from flask import Blueprint, jsonify, request, json, session from models.updateProfile import update_user from models.updateProfile import fetch_user_info +from events.eventDefinitions import updated_username +from publishers.kafkaPublishers import publish_username_updated_event + update_profile_bp = Blueprint("update",__name__) @update_profile_bp.route("/user/update", methods=["POST"]) def update_profile(): - user_id = session.get("user_id") + user_id = session.get("user_id") #gets session data - if user_id: + if user_id: #if user is logged in user_info = fetch_user_info(user_id) print(jsonify(user_info)) @@ -25,7 +30,7 @@ def update_profile(): gender = data.get("gender") - # Create a dictionary from user data + # Create a json object from user data user_data = { "user_id" : user_id, "email": email, @@ -35,13 +40,15 @@ def update_profile(): "gender": gender, } - # Convert to JSON - json_user_data = json.dumps(user_data) + update = update_user(user_data) #Send user info to database + if "message" in update: - update = update_user(user_data) #Send user info to database + event_data = {"user_id" : user_id, "new_username" : user_data["first_name"]} + event_message = updated_username(user_id, user_data["first_name"]) + publish_username_updated_event(event_data) - return jsonify(update, user_id) + return jsonify({"Update Status": update, "Username" : user_data["first_name"], "User ID" : user_id, "Event message" : event_message}) else: return {"error" : "null"} diff --git a/User_MicroService_Group3/app/events/__init__.py b/User_MicroService_Group3/app/events/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/User_MicroService_Group3/app/events/__pycache__/__init__.cpython-311.pyc b/User_MicroService_Group3/app/events/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95be18671d60d24a8dd5c89660bea97b034080d2 GIT binary patch literal 272 zcmXv}yJ`b55R_sPLcrt~)TT+3R3RA58B*l|7vp9@D7v*zM5jGgr-S>Fd_anj@5&Dt z+_{R**i+2T?i4foGo4<EjQU=z$N4wX3Gyg*7g>CXN|fS8zWfS4%lmFL_us_>EF*FR z(+swT*MJLlJ;H))YA|#W-m*)<cvyyPaCF_EXsyb`i~|&uIHFn+f5N=#O|V$0qBh=R z*kDvHs1<&wceHgNPaB8v5U8J>Wh#+-XHh>frS=X?+XD87RIOcboz}PQu)ln4s7fAZ We4aaxU&ZT8+liEND^A3deESD5ZcuFi literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/events/__pycache__/eventDefinitions.cpython-311.pyc b/User_MicroService_Group3/app/events/__pycache__/eventDefinitions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26189d001a07adbc3c51f25578fd46235d1830b5 GIT binary patch literal 492 zcmZWmJ4*vW5Z=8r#z%aBjiit*L<oW?b|Qi#VC4g%2(oaTw-d8?**#|OA_o>0{s$Wi zI}!hoTqXDi0_m)rJ0Fb;^UVzN?Kgb8&vSD#jLz03>pfBaD4XBIe~NK~iU+3HJ-c9v zcUjAeyk8RK2@0QLJWoJ8e#>sT@*aI+`bWh=g0`n)2(m<lDX5lT%)kl-swMLlzX zfmTJsz)es#CLF*EEx{V;;Us}8*9r0Y+TM|8#Beek<WXN98|a`Og6!BR8<3=vCp5Jt zjOCf30Xm)L!uCWrLxfzmZH5lSxy5U_uZE$CK#6ugjAJlY;Dk2f94^HvM15mpd!@lu z3xh))q3r?=bp*iy+AP_YVUozoi2F_*=xL)<ZH?PV@?!DF@1G}}CKu(Sx+cLLdvC74 zEj8bkS4TCku{L7gP+J?*lpVEr#m71|Sbh>t5qwVV4y?*z*uz<BE439WMn30!<V|qW I`483oFLtem;{X5v literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/events/eventDefinitions.py b/User_MicroService_Group3/app/events/eventDefinitions.py new file mode 100644 index 00000000..bb880664 --- /dev/null +++ b/User_MicroService_Group3/app/events/eventDefinitions.py @@ -0,0 +1,5 @@ +def updated_username(user_id, new_username): + + return {"event_type": "profile_updated", + "user_id": user_id, + "new_username": new_username} \ No newline at end of file diff --git a/User_MicroService_Group3/app/index.py b/User_MicroService_Group3/app/index.py index 32fd79e7..a22a9736 100644 --- a/User_MicroService_Group3/app/index.py +++ b/User_MicroService_Group3/app/index.py @@ -1,4 +1,4 @@ -from flask import Flask, redirect, url_for, request, render_template, make_response, session, abort +from flask import Flask, jsonify, redirect, json, url_for, request, render_template, make_response, session, abort from flask_cors import CORS from flask import jsonify from controllers.loginController import login_bp @@ -7,13 +7,20 @@ from controllers.updateProfileController import update_profile_bp from controllers.changePasswordController import change_password_bp from controllers.deleteProfileController import deleteProfile_bp from controllers.logoutController import logout_bp +from controllers.fetchUsernameController import fetch_username_bp +from controllers.showReviewsController import show_reviews_bp + +from config import DEBUG, SECRET_KEY, PORT +import os +import requests +import publishers app = Flask(__name__) CORS(app) -app.secret_key = 'Group3' +app.secret_key = SECRET_KEY @app.route('/') def index(): @@ -37,6 +44,21 @@ app.register_blueprint(deleteProfile_bp) app.register_blueprint(logout_bp) +app.register_blueprint(fetch_username_bp) + +app.register_blueprint(show_reviews_bp) + +publishers.create_profile_updated_topic() + + + + +@app.route("/userIDs", methods=["POST"]) +def userIDs(): + + #ids = request.json + #print(ids) + return 'hi' if __name__ == '__main__': - app.run(debug=True, port=5000) \ No newline at end of file + app.run(debug=DEBUG, port=PORT) \ No newline at end of file diff --git a/User_MicroService_Group3/app/models/__pycache__/changePassword.cpython-311.pyc b/User_MicroService_Group3/app/models/__pycache__/changePassword.cpython-311.pyc index 3e2f696425d98b4acece898d09560e3b644ec81a..efbc1602a81cf43627230b17ff6be9b650f9cba8 100644 GIT binary patch delta 23 dcmdn2y;+-YIWI340}zOE{Y&-Y*~qt46aYsU1?K<& delta 23 dcmdn2y;+-YIWI340}!mc_9OKY_eQ>@q5xMp2h9Kg diff --git a/User_MicroService_Group3/app/models/__pycache__/fetchUsername.cpython-311.pyc b/User_MicroService_Group3/app/models/__pycache__/fetchUsername.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae95206848ec046c1557589c2b224c793de637e2 GIT binary patch literal 2209 zcmd5-U1-}@6uy!yM{#UtcJtGuC02e44Rje}-4;r=;Uvx&Nz*Ymlm>xOq?<&otm|IM zaU7gc#vZ&-NC$-u#-LBxMqc{3=QZuKT?{pXL164*Z-P(=ec8@+Vkc?(kgyGQb#-*^ z`TNefKe|7LLIDKr+2mjNnSjvmY*26fKC^QPn1@J5I%lFZH_LI1=S_Z=hp%7?Y2U05 zWWKM_tf=!zG${VbTn9O~>6T3_V?I9(d_W_Xg*7Lo&uQF#X!a4|1!%N$8R$dQjGRN- z4Nz>tyVq8^0{7^Uwk}8LH9KDCR)qrps9wT>A#equfHpw0+0b$bY*`M++G}xr1s{FC z;M4i8hGl`LZQ$)|2o5nvy#a-z?NGsqY?CMnb8*V(9Vd;hLv;4`BPV!}@U5mgKY-}u zs^~=OV+0Fb5Wh!1@Eb7yn~gQ#&`pT5Dt;;c*O~62<TxjKkkcEo^!-1w%%NrBCdzUB zr(MAl?~fd+V+@MZE0>drsl?cIdB(=nQqx$T_~P1CS)U_AOp<ccITOpdMNDzc<g;=4 zBl#1`4!}zPxC(03#xkaqP}#8LdF*J5sVws}ta)-pUU_@Q!pj*ry;$EjBbt__FnW{u zV1Tkc?)t&RCe&@h%UH`g*p+ILiG^KJGl>lX2Er0{{h2(0KZ7eKSQf6Bp@!wS&530V zXB>lAgMODc^u}KVB-GC^#5-9`^R7Ti&gHPpWOA*&`f2Qn!m76wHJ#TMm1`Crr^XUi z#)+0qW6QCX&p}Hp)l_CIP*B@&@-ms1lUYh}UKt~hK9+9~dRvL>ORA+oy<>~2X<};u z+pP2(cuu~KwMC1VWWm684KQ`p&?re_x@2fL^(iIU%zKKO$tY=}W7Ae@lfW`#g%4%& zZg2rRwdrO8+72bKGVBPf&t2sCVq)x%_Sm<|1Em<KM$Wy6^gWOCl_LX{$UxD*{nkWL ztV-ea@LKqO_Pe>V)LW5yOH%K4xNV)Rk#aaz3CD`Uc1zepLi5?`nU4E+9(>^Sp<vWQ zT=ThVFuFdqHucT)z3Jj~wWXa2W7S~Ci{Sa^!Sm%{PbJt>s&!8Qjn|Lb&U!tk_l6jI z0a*Oqmz@yd-iU{IvF(8TCWT7j4<E;YKrc(f6=}F64Od&w6dm?>;eU#|ySw|c6$PQn z<G}G>)KVC*<7H{IB8`@$(F0)rzX0sD0wyG|>jh39tu}YyYmdOz_$uBxI*fiDZcSVe zo-{?rL&B3TU*aO#3WY$j)g4X9!qz1wc`Az_d3r%${Ka=BIt4gL;=HNaw<){vXbTXx zdv9kB>HEKe)c#$~P8mDNwLSSW+5r~PHXyI05pc<x_+#1)Lv|n7lRzL#j;o@s($QW; Yp}V!Giry_9?Vi7vi+Sicq3n+R8=}_$z5oCK literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/models/__pycache__/getUsers.cpython-311.pyc b/User_MicroService_Group3/app/models/__pycache__/getUsers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd54bdac2b3189ffb26e70c80dcb6d7a9d4b3f61 GIT binary patch literal 272 zcmXv}%Sr=55S&R+f)M<Lxq9*9Ed)U};K>K9A(w_Q&bGUQv(rn@&f<QFAK*d6&+-QX zxrH2@4M`oUtE&!O{XLyth=kvdJr474pcCX#Y|oSU6otsem3;gWJWBg^2zOuE43+^o zfUbK}!IQ@Y+YVttCf4ZN0M98UuN^FX3OLxdSM;Xx$c#N?6gi+;5x>J-(P?k6P+6s& zLtkQ0)~gl1suwhsCr72la5%Vru!bo|?ySM}JyUFMKsOE4RG<q`VteRy-SoT3Jekqq WEuW>%!&l)l(Pk{A+=vtLIC=lS98v%P literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/models/__pycache__/updateProfile.cpython-311.pyc b/User_MicroService_Group3/app/models/__pycache__/updateProfile.cpython-311.pyc index 43ec1e62b7e96678f2be3c7811088ea64c8e1774..a3cc094c4a2bb3f0c99ed37c439242aab85aaf1a 100644 GIT binary patch delta 20 acmeBG?p5Yq&dbZi00dede>QSA2?78y`ULa< delta 20 acmeBG?p5Yq&dbZi00ezIe{JM$5(EG@QU%8V diff --git a/User_MicroService_Group3/app/models/changePassword.py b/User_MicroService_Group3/app/models/changePassword.py index 18d40df2..7cb162b6 100644 --- a/User_MicroService_Group3/app/models/changePassword.py +++ b/User_MicroService_Group3/app/models/changePassword.py @@ -18,17 +18,17 @@ def check_old_password(data): # Check if the email already exists email_check_query = "SELECT COUNT(*) FROM dbo.User_table WHERE UserID = ?" - cursor.execute(email_check_query, user_id) + cursor.execute(email_check_query, user_id) #executes the query count = cursor.fetchone()[0] if count == 0: return ({"Error" : "Email does not exist"}, 0) else: - + #selects password information from database query = "SELECT t1.Email, t1.UserID, t2.Iterations, t2.PasswordHash, t2.PasswordSalt FROM dbo.User_table as t1 INNER JOIN dbo.AuthInfo as t2 ON t1.UserID = t2.UserID where t1.UserID= ?" - cursor.execute(query, user_id) + cursor.execute(query, user_id) #executes query row = cursor.fetchone() @@ -67,13 +67,13 @@ def set_new_password(data): user_id = data["user_id"] - # + #selects user ID select_userID_query = "SELECT UserID from dbo.User_table where UserID = ?" cursor.execute(select_userID_query, user_id) UserID = cursor.fetchone()[0] - # + #updates password update_authinfo_query = '''UPDATE dbo.AuthInfo SET PasswordHash = ?, PasswordSalt = ?, Iterations = ?, TempPlainText = ? WHERE UserID = ?''' diff --git a/User_MicroService_Group3/app/models/fetchUsername.py b/User_MicroService_Group3/app/models/fetchUsername.py new file mode 100644 index 00000000..437cac41 --- /dev/null +++ b/User_MicroService_Group3/app/models/fetchUsername.py @@ -0,0 +1,39 @@ +from flask import jsonify +import pyodbc +from models.database_connection import connect_db + + +def get_username(id): + + try: #error handling + + connection = connect_db() + cursor = connection.cursor() + + query = "SELECT Username FROM dbo.User_table where UserID = ?" + cursor.execute(query, id) + + row = cursor.fetchone() #fetch data + + if row: + return row[0] # Assuming the username is in the first column + else: + return None + + #connection.close() + + return username + + except pyodbc.Error as e: #error handling + print(f"Database error in fetch_user_info: {e}") + return None + + except Exception as e: #error handling + print(f"Unexpected error occured in fetch_user_info: {e}") + return None + + finally: + if cursor: + cursor.close() + if connection: + connection.close() diff --git a/User_MicroService_Group3/app/models/getUsers.py b/User_MicroService_Group3/app/models/getUsers.py new file mode 100644 index 00000000..f056e2de --- /dev/null +++ b/User_MicroService_Group3/app/models/getUsers.py @@ -0,0 +1,38 @@ +#from app import db +from flask import jsonify +import pyodbc +from models.database_connection import connect_db + + +def fetch_user_info(id): + + try: #error handling + + connection = connect_db() + cursor = connection.cursor() + + query = "SELECT First_name, Last_name FROM dbo.User_table where UserID = ?" + cursor.execute(query, id) + + row = cursor.fetchone() #fetch data + + columns = [column[0] for column in cursor.description] + user_data = dict(zip(columns, row)) + + #connection.close() + + return user_data + + except pyodbc.Error as e: #error handling + print(f"Database error in fetch_user_info: {e}") + return None + + except Exception as e: #error handling + print(f"Unexpected error occured in fetch_user_info: {e}") + return None + + finally: + if cursor: + cursor.close() + if connection: + connection.close() \ No newline at end of file diff --git a/User_MicroService_Group3/app/publishers/__init__.py b/User_MicroService_Group3/app/publishers/__init__.py new file mode 100644 index 00000000..beb65e5e --- /dev/null +++ b/User_MicroService_Group3/app/publishers/__init__.py @@ -0,0 +1 @@ +from publishers.kafkaPublishers import create_profile_updated_topic \ No newline at end of file diff --git a/User_MicroService_Group3/app/publishers/__pycache__/__init__.cpython-311.pyc b/User_MicroService_Group3/app/publishers/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e5ad7960c3085c3269be00737e82ddc12a6c966 GIT binary patch literal 369 zcmZurO-lnY5KUT?BJ|=>6!yB8Uc8A2vIS3Sp_YOKLYmBWL$gVkYzq4W{0;tu;=l1I zy?XMd^wyK9_;GQVkN23z%v<&Q2PDPA$6i^a`MM)N(fJ0O!vr3QB8nPP(|byZ>WoR= zecK6gx;~Z&q5<yFmD&K0UL~q{<GhwPd1rm(<ILz#0fxaslnXKX<=9O(p2%i*YP%}V z*d!zs6Ll*qc57jXdI@akWURq9fsNAESz*}3rUeGww3#cjaYTfc6)s|cZ0c~qF4a<4 z2`VcpVGP(ggiPCP3bX7EWM!Rka}D9^A-~oV-57AGCGabB(VsHmJ^M4xIM-G;oDY1v f?VZ<7MFSVuOTKBUaFW`4ms0vdis%0l_mkoi7pZkz literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc b/User_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3847106fe73d1b4414eb89e2fd3d5401f6c225f7 GIT binary patch literal 2334 zcma)7O>7fK6rT0&+G9HogxCRG1SX)Sc1VJtjUY{`&`=`L;)Di-Fjn1VcbqI)?^?6# zq>1dxYAZFzs;WeeoG6H>>apsnrI#Mp(MpL{LPDx?;Fc<fB2Im?{z)9D)VH&5XWqP- z_vX!e-~Jehgb<MPkC^ZABlH&=G>LC?cGA$fj})YE8Y*xZj$?hF<}2_Sz93`-Z_I0A zM)V=VDZ-lgkVEJRymiX>75_IV6Ho%cvBJ-wB!0oBlAIg)Sjx{!)6`H(GNDPId(abH zQVOa*p{Yc-T%0D0H;kexr(bnyhAe4whG~slJbUrnW6tfmYZ#VkQK^_S30)x6lp9vP zj|iNdW9L_3_mS1|3BhUBeC>W#kiu8M|B4S@zKkC1(e`%p*hAn?TEmJ^=E}kXN6%Qy zR)aw1EAtQsu>GVNM^q7E&(^4^%f4lCmQ(y|frmcOhqq2Ft~1`7#AyoGgJ=Ml8!J*H zuWBS$Dk_pil$^z)^MZMs<Xu6R3dHTyONCrfqLyl@hHkotC@E^HEU{58FUgicuRydz zI$5kQH{HmBq^WGfoS|z=Nr4K?SXfg{tD!>K5#5MP3Dfednn}OgA+g)a$@S|BdGZ|d zf<{1}cCtmCb!mZE5}1(O;I3hIu!KjiewrA`-h_KJvr=J6p36?@<T6zkNcOTJmkN*! zW_B884PDZ*H+7hxrfMxEjC^9IL@8OyP8cO>lEf{8&Sx(v3z9AqB{4B4X&TXIiJ4IK z#4U0+af8Tnx}h1fDlt8SxofISjTy)wRVKMfYLtrSvr@5`Etc*=0OpuW^IoR5#)HKr z_gEtoZ@dtC1P;c^%lsNx6>W8&vWKtO-IKNMNvC_V`pLE*9ZFWOZpM15>CK~YTj&8v zPwz%-U_CZaiw!xkp=ugL_|WQcJJ1JhD|+lf>X*;#_XYf;mQnk&KQIJ$v**KzNo zrAPCB#%$bM!&45PvYTx?i10hGdI#J<^4_Fop=SxXvkB7n^0?R1E2Dj7!dWac8uaFb zR=6_vV2@T)8_I59(XH|ANnh~=QQ7xkPciLT`x>-Vc#Gv&gA{+eryOdV4V3wNtbjaf zx4KUggC_o8nnBPE{+FiScM4h2<}5;|5sg=bHlIReVZSH0q2w#Vmx7M#-$iZ_eZk*G zi|ug_@9w+XYX_$~fF#3d%F=LIELr)13jn$zRC<ZLU_uxLEVV$4lC>PaMod$hB?%KM zEn${q8OHgNrY)UZ_TOL_GqN0-Zeq&Fa$qW-H;FZ}eE5n4aHJ$GgDq7Oh59}t$qrYz z2i59|N~usZT?}>N;k+v_J=afk*-(hf&l1ZOi&O=)7d@bGgDvcG{f1}84Sw{6Oo|M^ zTrsbe%(<lKhR6c=n)4u~(f15?FbN<O{1m{>0ZL?pD!CT=aKvN@=7A193_bUFqtJ6D zfFFikEpYWL&>>Jd0k8QtFsS9O*bnj5tF^8^r>n1eb*uZW`(xja*(Wdj7TOrUzCM24 z{`7WjJmZXKz8kA`-*LL{K)L$@;+f6(+Z*xJdOY>>IXj-J#fP2v@XCQ_IAV9EYPjFQ z{Wk80;mX|V0q4j-4G%ha(8hyIq^(Xl$KI>qVFwS}c$kUQ)f3Lqp&CBx;Ip>ZUOo#) zw-G0v*=64DeUG|Y`-6$S?IqAQ4@=;?C3Jk7{wiG)qK*)?o6S55r~X~Mbo#>-dYTGN zbn;K%Jvb5M{|JiEPX=Al14qiR#0`7>LGP#F{X@Lp20adQG{G3dMK7R_5oH^DH}DFN z79cq^@&P>$GKN0p0x)ol<2KO=yS;6qbM~9sa}=(6&-3t+l`*^jeLFl_3y(VC(JJ1? UUEDOcjrQ<Vgo|yX*O}+nzbA27T>t<8 literal 0 HcmV?d00001 diff --git a/User_MicroService_Group3/app/publishers/kafkaPublishers.py b/User_MicroService_Group3/app/publishers/kafkaPublishers.py new file mode 100644 index 00000000..042a5c13 --- /dev/null +++ b/User_MicroService_Group3/app/publishers/kafkaPublishers.py @@ -0,0 +1,44 @@ +from kafka import KafkaProducer +from kafka.admin import KafkaAdminClient, NewTopic + +import json + +producer = KafkaProducer(bootstrap_servers="localhost:9092") + + + +def create_profile_updated_topic(): + # Create KafkaAdminClient instance + admin_client = KafkaAdminClient(bootstrap_servers="localhost:9092") + + # Define the topic name and configuration + topic_name = "profile_updated_topic" + num_partitions = 1 + replication_factor = 1 + + # Retrieve the list of existing topics + topic_metadata = admin_client.list_topics() + + # Check if the topic already exists + if topic_name not in topic_metadata: + # Define the configuration for the new topic + new_topic = NewTopic(name=topic_name, num_partitions=num_partitions, replication_factor=replication_factor) + # Create the new topic + admin_client.create_topics(new_topics=[new_topic], validate_only=False) + + + +def publish_username_updated_event(event_data): + # Serialize the event data to JSON + event_json = json.dumps(event_data) + # Publish the event to the Kafka topic + data_to_send = producer.send("profile_updated_topic", value=event_json.encode("utf-8")) + try: + record_metadata = data_to_send.get(timeout=10) + print("Message sent successfully!") + print("Topic:", record_metadata.topic) + print("Partition:", record_metadata.partition) + print("Offset:", record_metadata.offset) + except Exception as e: + print("Failed to send message:", e) + producer.flush() \ No newline at end of file -- GitLab