Skip to content

Commit 7c91fe0

Browse files
Seluj78gmorer
andauthored
Merge pull request #149 from Seluj78/complete-profile
Co-authored-by: gmorer <gmorer@pm.me>
2 parents c45a409 + 651b258 commit 7c91fe0

File tree

20 files changed

+565
-91
lines changed

20 files changed

+565
-91
lines changed

.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
env/
1+
venv/
22
__pycache__/
33
.git
44
frontend/node_modules

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ADD .env .
66
RUN export $(cat .env | xargs)
77
RUN npm run build
88

9-
FROM python:3.7.7-buster
9+
FROM python:3.8.3-buster
1010
WORKDIR /www
1111
ADD backend .
1212
ADD .env .

PyMatcha.postman_collection.json

Lines changed: 129 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@
123123
"tests[\"JSON return code is 400\"] = response.code == 400",
124124
"",
125125
"tests[\"success is true\"] = response.success == false",
126-
"tests[\"Message is correct\"] = response.error.message == \"Missing key(s) ['username', 'first_name', 'last_name'] to perform action.\"",
126+
"tests[\"Message is correct\"] = response.error.message == \"Missing keys ['username', 'first_name', 'last_name'].\"",
127127
"tests[\"Error type is Bad Request\"] = response.error.type == \"BadRequestError\""
128128
],
129129
"type": "text/javascript"
@@ -804,7 +804,7 @@
804804
"tests[\"JSON return code is 400\"] = response.code == 400",
805805
"",
806806
"tests[\"success is true\"] = response.success == false",
807-
"tests[\"Message is correct\"] = response.error.message == \"Missing key(s) ['username'] to perform action.\"",
807+
"tests[\"Message is correct\"] = response.error.message == \"Missing keys ['username'].\"",
808808
"tests[\"Error type is Bad Request\"] = response.error.type == \"BadRequestError\""
809809
],
810810
"type": "text/javascript"
@@ -855,8 +855,10 @@
855855
"",
856856
"tests[\"success is true\"] = response.success == true",
857857
"",
858-
"pm.collectionVariables.set(\"user_access_token\", response.tokens.access_token);",
859-
"pm.collectionVariables.set(\"user_refresh_token\", response.tokens.refresh_token);"
858+
"tests[\"Is profile completed is 0\"] = response.return.is_profile_completed == 0",
859+
"",
860+
"pm.collectionVariables.set(\"user_access_token\", response.return.access_token);",
861+
"pm.collectionVariables.set(\"user_refresh_token\", response.return.refresh_token);"
860862
],
861863
"type": "text/javascript"
862864
}
@@ -906,8 +908,10 @@
906908
"",
907909
"tests[\"success is true\"] = response.success == true",
908910
"",
909-
"pm.collectionVariables.set(\"user_access_token\", response.tokens.access_token);",
910-
"pm.collectionVariables.set(\"user_refresh_token\", response.tokens.refresh_token);"
911+
"tests[\"Is profile completed is 0\"] = response.return.is_profile_completed == 0",
912+
"",
913+
"pm.collectionVariables.set(\"user_access_token\", response.return.access_token);",
914+
"pm.collectionVariables.set(\"user_refresh_token\", response.return.refresh_token);"
911915
],
912916
"type": "text/javascript"
913917
}
@@ -1282,6 +1286,114 @@
12821286
],
12831287
"protocolProfileBehavior": {}
12841288
},
1289+
{
1290+
"name": "Profile",
1291+
"item": [
1292+
{
1293+
"name": "Complete profile",
1294+
"event": [
1295+
{
1296+
"listen": "test",
1297+
"script": {
1298+
"id": "a0f4bed4-f29c-46ff-a16b-66db85d46a87",
1299+
"exec": [
1300+
"var response = JSON.parse(responseBody);",
1301+
"",
1302+
"",
1303+
"pm.test(\"Status code is 200\", function () {",
1304+
" pm.response.to.have.status(200);",
1305+
"});",
1306+
"",
1307+
"",
1308+
"tests[\"success is true\"] = response.success == true",
1309+
"tests[\"Message is correct\"] = response.message == \"Profile completed !\"",
1310+
""
1311+
],
1312+
"type": "text/javascript"
1313+
}
1314+
}
1315+
],
1316+
"request": {
1317+
"method": "POST",
1318+
"header": [],
1319+
"body": {
1320+
"mode": "raw",
1321+
"raw": "{\n\t\"orientation\": \"heterosexual\",\n\t\"bio\": \"Nunc faucibus velit metus, nec iaculis sem fringilla ut. Nullam vel vulputate diam. Vivamus vehicula, enim at hendrerit tincidunt, leo sapien maximus nisi, nec suscipit arcu nisi a turpis. Suspendisse rutrum quis quam et sollicitudin. Proin commodo justo non dui tempor, at maximus velit vulputate. Integer vitae porta nulla, ut congue est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin purus ex, venenatis vel aliquet a, interdum sit amet quam. Donec ac volutpat dui. In ornare augue in nisi efficitur varius. Donec hendrerit nunc a pulvinar posuere. Donec malesuada eros quam, eget pharetra nunc elementum in.\"\n}",
1322+
"options": {
1323+
"raw": {
1324+
"language": "json"
1325+
}
1326+
}
1327+
},
1328+
"url": {
1329+
"raw": "{{host}}/profile/complete",
1330+
"host": [
1331+
"{{host}}"
1332+
],
1333+
"path": [
1334+
"profile",
1335+
"complete"
1336+
]
1337+
}
1338+
},
1339+
"response": []
1340+
},
1341+
{
1342+
"name": "Login after profile completed",
1343+
"event": [
1344+
{
1345+
"listen": "test",
1346+
"script": {
1347+
"id": "c3bcacc7-f9f6-42ad-8590-2022cfae9c6f",
1348+
"exec": [
1349+
"var response = JSON.parse(responseBody);",
1350+
"",
1351+
"",
1352+
"pm.test(\"Status code is 200\", function () {",
1353+
" pm.response.to.have.status(200);",
1354+
"});",
1355+
"",
1356+
"tests[\"JSON return code is 200\"] = response.code == 200",
1357+
"",
1358+
"tests[\"success is true\"] = response.success == true",
1359+
"",
1360+
"tests[\"Is profile completed is 0\"] = response.return.is_profile_completed == 1",
1361+
"",
1362+
"pm.collectionVariables.set(\"user_access_token\", response.return.access_token);",
1363+
"pm.collectionVariables.set(\"user_refresh_token\", response.return.refresh_token);"
1364+
],
1365+
"type": "text/javascript"
1366+
}
1367+
}
1368+
],
1369+
"request": {
1370+
"method": "POST",
1371+
"header": [],
1372+
"body": {
1373+
"mode": "raw",
1374+
"raw": "{\n\t\"password\": \"{{user_password}}\",\n\t\"username\": \"{{user_email}}\"\n}",
1375+
"options": {
1376+
"raw": {
1377+
"language": "json"
1378+
}
1379+
}
1380+
},
1381+
"url": {
1382+
"raw": "{{host}}/auth/login",
1383+
"host": [
1384+
"{{host}}"
1385+
],
1386+
"path": [
1387+
"auth",
1388+
"login"
1389+
]
1390+
}
1391+
},
1392+
"response": []
1393+
}
1394+
],
1395+
"protocolProfileBehavior": {}
1396+
},
12851397
{
12861398
"name": "Delete user after tests",
12871399
"event": [
@@ -1382,67 +1494,67 @@
13821494
],
13831495
"variable": [
13841496
{
1385-
"id": "6c8b7fc6-9cc7-4d64-a3a8-6906042342b6",
1497+
"id": "f4dd475b-c423-4497-a1d7-826619651283",
13861498
"key": "host",
13871499
"value": "http://127.0.0.1:5000",
13881500
"type": "string"
13891501
},
13901502
{
1391-
"id": "ddad86e9-22e5-4a88-b52d-301816ef3a36",
1503+
"id": "8d82efce-58a4-4ae6-be77-3f9a94c64aa4",
13921504
"key": "user_id",
13931505
"value": "",
13941506
"type": "string"
13951507
},
13961508
{
1397-
"id": "5d18d3f6-eaeb-40d7-8a7c-c7b0d964553c",
1509+
"id": "54e97677-add0-44ce-b4de-08e78149669d",
13981510
"key": "user_email",
13991511
"value": "foo@example.org",
14001512
"type": "string"
14011513
},
14021514
{
1403-
"id": "faf5a9f1-4700-4834-9c27-828bd5a91ce7",
1515+
"id": "f13b4302-ae17-4f05-bd3d-0092d7d0e988",
14041516
"key": "user_username",
14051517
"value": "bar",
14061518
"type": "string"
14071519
},
14081520
{
1409-
"id": "ed8d0627-3dca-497c-a0ac-3ea8d91f44ee",
1521+
"id": "b71e8f9f-9932-4c65-b1b8-88bbe02146c2",
14101522
"key": "user_password",
14111523
"value": "admin",
14121524
"type": "string"
14131525
},
14141526
{
1415-
"id": "0d707d74-159d-44d8-ba14-d6d481e06f36",
1527+
"id": "d567e6be-d3ae-418d-bc4a-a2b8ec7971a3",
14161528
"key": "user_firstname",
14171529
"value": "Foo",
14181530
"type": "string"
14191531
},
14201532
{
1421-
"id": "af2785be-3f97-4b93-8715-6d3fc078f780",
1533+
"id": "9f99c685-7bf2-4774-b694-c3fcebb92b84",
14221534
"key": "user_lastname",
14231535
"value": "Bar",
14241536
"type": "string"
14251537
},
14261538
{
1427-
"id": "acc6eed3-ff7a-427e-ad0c-3759ce4d730b",
1539+
"id": "34adee57-0702-4c96-9efb-58a80542d55d",
14281540
"key": "debug_token",
14291541
"value": "xX69jules69Xx",
14301542
"type": "string"
14311543
},
14321544
{
1433-
"id": "b0753752-b0e6-4772-aefd-c5fb69ea93ff",
1545+
"id": "dcd1f01b-44a4-4750-a05c-af21292576b6",
14341546
"key": "user_access_token",
14351547
"value": "",
14361548
"type": "string"
14371549
},
14381550
{
1439-
"id": "99791095-2cf9-486c-9573-1e21bb25012b",
1551+
"id": "633549e9-b8aa-42ed-8178-6a91d38961b8",
14401552
"key": "user_refresh_token",
14411553
"value": "",
14421554
"type": "string"
14431555
},
14441556
{
1445-
"id": "fb718e68-8130-4d40-ab14-4e5816a8f1e7",
1557+
"id": "b712d83c-9221-4571-9945-6fc52fcd167f",
14461558
"key": "expired_token",
14471559
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTAyNDIyNjQsIm5iZiI6MTU5MDI0MjI2NCwianRpIjoiNTM0ZGI5NzQtOWE4Ni00MGViLWE1NDEtMDg3N2ZmNzQ3NDVhIiwiZXhwIjoxNTkwMjQyMzI0LCJpZGVudGl0eSI6eyJpZCI6NTEyLCJlbWFpbCI6ImZvb0BleGFtcGxlLm9yZyIsInVzZXJuYW1lIjoiYmFyIiwiaXNfb25saW5lIjp0cnVlLCJkYXRlX2xhc3RzZWVuIjoiU2F0LCAyMyBNYXkgMjAyMCAxMzo1Nzo0NCBHTVQifSwiZnJlc2giOnRydWUsInR5cGUiOiJhY2Nlc3MifQ.NTp2P0WNkXDwzuzrcNIQdeAfizQ57HQgkzBLSvY1yHU",
14481560
"type": "string"

backend/PyMatcha/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,13 @@ def check_if_token_is_revoked(decrypted_token):
189189
from PyMatcha.routes.api.ping_pong import ping_pong_bp
190190
from PyMatcha.routes.api.user import user_bp
191191
from PyMatcha.routes.api.auth import auth_bp
192+
from PyMatcha.routes.api.profile import profile_bp
192193

193194
logging.debug("Registering Flask blueprints")
194195
application.register_blueprint(ping_pong_bp)
195196
application.register_blueprint(user_bp)
196197
application.register_blueprint(auth_bp)
198+
application.register_blueprint(profile_bp)
197199

198200
if application.debug:
199201
logging.debug("Registering debug route")

backend/PyMatcha/models/user.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,12 @@ def create(
119119
raise ConflictError("Gender must be male, female or other, not {}".format(gender), "Try again")
120120

121121
# Check correct orientation
122-
if orientation not in ["heterosexual", "homosexual", "bisexual"]:
123-
logging.error("Sexual Orientation must be heterosexual, homosexual or bisexual, not {}".format(orientation))
122+
if orientation not in ["heterosexual", "homosexual", "bisexual", "other"]:
123+
logging.error(
124+
"Sexual Orientation must be heterosexual, homosexual, bisexual or other, not {}".format(orientation)
125+
)
124126
raise ConflictError(
125-
"Sexual Orientation must be heterosexual, homosexual or bisexual, not {}".format(orientation),
127+
"Sexual Orientation must be heterosexual, homosexual, bisexual or other, not {}".format(orientation),
126128
"Try again",
127129
)
128130

backend/PyMatcha/routes/api/auth.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
from PyMatcha.utils import hash_password
4141
from PyMatcha.utils.confirm_token import confirm_token
4242
from PyMatcha.utils.confirm_token import generate_confirmation_token
43-
from PyMatcha.utils.decorators import validate_required_params
43+
from PyMatcha.utils.decorators import validate_params
4444
from PyMatcha.utils.mail import send_mail_text
4545

4646
User = user.User
@@ -56,7 +56,7 @@
5656

5757

5858
@auth_bp.route("/auth/register", methods=["POST"])
59-
@validate_required_params(REQUIRED_KEYS_USER_CREATION)
59+
@validate_params(REQUIRED_KEYS_USER_CREATION)
6060
def api_create_user():
6161
current_app.logger.debug("/auth/register -> Call")
6262
data = request.get_json()
@@ -117,7 +117,7 @@ def confirm_email(token):
117117

118118

119119
@auth_bp.route("/auth/password/forgot", methods=["POST"])
120-
@validate_required_params(REQUIRED_KEYS_PASSWORD_FORGOT)
120+
@validate_params(REQUIRED_KEYS_PASSWORD_FORGOT)
121121
def forgot_password():
122122
current_app.logger.debug("/auth/password/forgot -> Call")
123123
data = request.get_json()
@@ -141,7 +141,7 @@ def forgot_password():
141141

142142

143143
@auth_bp.route("/auth/password/reset", methods=["POST"])
144-
@validate_required_params(REQUIRED_KEYS_PASSWORD_RESET)
144+
@validate_params(REQUIRED_KEYS_PASSWORD_RESET)
145145
def reset_password():
146146
current_app.logger.debug("/auth/password/reset -> Call")
147147
data = request.get_json()
@@ -174,7 +174,7 @@ def reset_password():
174174

175175

176176
@auth_bp.route("/auth/login", methods=["POST"])
177-
@validate_required_params(REQUIRED_KEYS_LOGIN)
177+
@validate_params(REQUIRED_KEYS_LOGIN)
178178
def auth_login():
179179
current_app.logger.debug("/auth/login -> Call")
180180
data = request.get_json()
@@ -189,16 +189,9 @@ def auth_login():
189189
current_app.logger.debug("/auth/login -> Password invalid")
190190
raise UnauthorizedError("Incorrect username or password", "Try again")
191191

192-
# access_token = fjwt.create_access_token(
193-
# identity=get_user_safe_dict(user), expires_delta=datetime.timedelta(hours=2)
194-
# )
195-
# TODO: Handle expiry for token
196192
if not u.is_confirmed:
197193
current_app.logger.debug("/auth/login -> User is trying to login unconfirmed")
198194
raise UnauthorizedError("User needs to be confirmed first.", "Try again when you have confirmed your email")
199-
# u.is_online = True
200-
# u.date_lastseen = datetime.datetime.utcnow()
201-
# u.save()
202195
access_token = fjwt.create_access_token(identity=u.get_base_info(), fresh=True)
203196
refresh_token = fjwt.create_refresh_token(identity=u.get_base_info())
204197
access_jti = fjwt.get_jti(access_token)
@@ -209,22 +202,20 @@ def auth_login():
209202

210203
current_app.logger.debug("/auth/login -> Returning access token for user {}".format(username))
211204
redis.set("user:" + str(u.id), datetime.datetime.utcnow().timestamp())
212-
tokens = {"access_token": access_token, "refresh_token": refresh_token}
213-
return SuccessOutput("tokens", tokens)
205+
ret = {"access_token": access_token, "refresh_token": refresh_token, "is_profile_completed": u.is_profile_completed}
206+
return SuccessOutput("return", ret)
214207

215208

216209
@auth_bp.route("/auth/refresh", methods=["POST"])
217210
@fjwt.jwt_refresh_token_required
218211
def refresh():
219-
# Do the same thing that we did in the login endpoint here
220212
current_user = fjwt.get_jwt_identity()
221213
access_token = fjwt.create_access_token(identity=current_user)
222214
access_jti = fjwt.get_jti(encoded_token=access_token)
223215
redis.set("jti:" + access_jti, "false", ACCESS_TOKEN_EXPIRES * 1.2)
224216
return SuccessOutput("access_token", access_token)
225217

226218

227-
# Endpoint for revoking the current users access token
228219
@auth_bp.route("/auth/access_revoke", methods=["DELETE"])
229220
@fjwt.jwt_required
230221
def logout():
@@ -233,7 +224,6 @@ def logout():
233224
return Success("Access token revoked")
234225

235226

236-
# Endpoint for revoking the current users refresh token
237227
@auth_bp.route("/auth/refresh_revoke", methods=["DELETE"])
238228
@fjwt.jwt_refresh_token_required
239229
def logout2():
@@ -243,7 +233,7 @@ def logout2():
243233

244234

245235
@auth_bp.route("/auth/confirm/new", methods=["POST"])
246-
@validate_required_params(REQUIRED_KEYS_NEW_EMAIL_CONF)
236+
@validate_params(REQUIRED_KEYS_NEW_EMAIL_CONF)
247237
def request_new_email_conf():
248238
current_app.logger.debug("/auth/confirm/new -> Call")
249239
data = request.get_json()
@@ -256,7 +246,7 @@ def request_new_email_conf():
256246
else:
257247
if u.is_confirmed:
258248
current_app.logger.debug("/auth/confirm/new -> User found, Already confirmed.")
259-
pass
249+
return Success("User already confirmed")
260250
else:
261251
current_app.logger.debug("/auth/confirm/new -> User found, sending new confirmation email")
262252
token = generate_confirmation_token(email=email, token_type="confirm")

0 commit comments

Comments
 (0)