diff --git a/app/backend/src/couchers/errors.py b/app/backend/src/couchers/errors.py index 2335fd325b..b957f63c91 100644 --- a/app/backend/src/couchers/errors.py +++ b/app/backend/src/couchers/errors.py @@ -22,6 +22,8 @@ HOST_REQUEST_IN_PAST = "This host request is in the past." HOST_REQUEST_NOT_FOUND = "Couldn't find that host request." HOST_REQUEST_SENT_OR_RECEIVED = "Can't only list sent and also only received requests." +HOSTING_STATUS_REQUIRED = "Hosting status is required." +INVALID_BIRTHDATE = "Invalid birthdate." INVALID_COLOR = "Invalid color." INVALID_DATE = "Invalid date." INVALID_EMAIL = "Invalid email." diff --git a/app/backend/src/couchers/servicers/auth.py b/app/backend/src/couchers/servicers/auth.py index 405dcdc0ea..3191b03b63 100644 --- a/app/backend/src/couchers/servicers/auth.py +++ b/app/backend/src/couchers/servicers/auth.py @@ -11,6 +11,7 @@ from couchers.interceptors import AuthValidatorInterceptor from couchers.models import LoginToken, SignupToken, User, UserSession from couchers.tasks import send_login_email, send_signup_email +from couchers.servicers.api import hostingstatus2sql from couchers import errors from pb import auth_pb2, auth_pb2_grpc from sqlalchemy import func @@ -160,7 +161,10 @@ def CompleteSignup(self, request, context): context.abort(grpc.StatusCode.NOT_FOUND, errors.INVALID_TOKEN) # should be in YYYY/MM/DD format, will raise exception if can't parse - birthdate = datetime.fromisoformat(request.birthdate) + try: + birthdate = datetime.fromisoformat(request.birthdate) + except: + context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_BIRTHDATE) # check email again if not is_valid_email(signup_token.email): @@ -175,13 +179,18 @@ def CompleteSignup(self, request, context): context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_NAME) + if not request.hosting_status: + context.abort(grpc.StatusCode.INVALID_ARGUMENT, + errors.HOSTING_STATUS_REQUIRED) + user = User( email=signup_token.email, username=request.username, name=request.name, city=request.city, gender=request.gender, - birthdate=birthdate + birthdate=birthdate, + hosting_status=hostingstatus2sql[request.hosting_status] ) # happens in same transaction diff --git a/app/backend/src/tests/test_auth.py b/app/backend/src/tests/test_auth.py index 2b4ff6a0b8..099e799b4f 100644 --- a/app/backend/src/tests/test_auth.py +++ b/app/backend/src/tests/test_auth.py @@ -5,7 +5,7 @@ from couchers.models import Base, SignupToken, LoginToken, User from couchers.servicers.auth import Auth -from pb import auth_pb2, auth_pb2_grpc +from pb import auth_pb2, auth_pb2_grpc, api_pb2 from tests.test_fixtures import db @@ -58,7 +58,8 @@ def test_basic_signup(db): name="Räksmörgås", city="Minas Tirith", birthdate="1980-12-31", - gender="Robot")) + gender="Robot", + hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST)) assert isinstance(reply.token, str) diff --git a/app/frontend/package.json b/app/frontend/package.json index f4e39213b5..63bea3ab04 100644 --- a/app/frontend/package.json +++ b/app/frontend/package.json @@ -13,19 +13,20 @@ "core-js": "^3.6.5", "google-protobuf": "^3.12.2", "grpc-web": "^1.1.0", + "markdown-it": "^10.0.0", "moment": "^2.26.0", "prettier": "^2.0.5", "vue": "^2.6.11", "vue-class-component": "^7.2.3", "vue-property-decorator": "^8.4.2", "vue-router": "^3.2.0", - "vue-simple-markdown": "^1.1.4", "vuetify": "^2.2.11", "vuex": "^3.4.0", "vuex-persistedstate": "^3.0.1" }, "devDependencies": { "@types/google-protobuf": "^3.7.2", + "@types/markdown-it": "^10.0.2", "@typescript-eslint/eslint-plugin": "^2.33.0", "@typescript-eslint/parser": "^2.33.0", "@vue/cli-plugin-babel": "~4.4.0", diff --git a/app/frontend/src/components/Drawer.vue b/app/frontend/src/components/Drawer.vue index 45da84fa86..da6efa0624 100644 --- a/app/frontend/src/components/Drawer.vue +++ b/app/frontend/src/components/Drawer.vue @@ -63,7 +63,12 @@ Friends - + mdi-account-group diff --git a/app/frontend/src/components/EditableDropdown.vue b/app/frontend/src/components/EditableDropdown.vue index 143e2059d7..d0e2254158 100644 --- a/app/frontend/src/components/EditableDropdown.vue +++ b/app/frontend/src/components/EditableDropdown.vue @@ -18,10 +18,6 @@ diff --git a/app/frontend/src/components/ReportDialogButton.vue b/app/frontend/src/components/ReportDialogButton.vue index 70338ee4ce..05146cce01 100644 --- a/app/frontend/src/components/ReportDialogButton.vue +++ b/app/frontend/src/components/ReportDialogButton.vue @@ -34,10 +34,10 @@ diff --git a/app/frontend/src/views/HostRequests.vue b/app/frontend/src/views/HostRequests.vue index b650391a47..9e6d7e5ac9 100644 --- a/app/frontend/src/views/HostRequests.vue +++ b/app/frontend/src/views/HostRequests.vue @@ -190,7 +190,7 @@ import { } from "../pb/requests_pb" import { client, requestsClient } from "../api" import { mapState } from "vuex" -import { HostRequest } from "@/pb/requests_pb" +import { HostRequest } from "../pb/requests_pb" import ErrorAlert from "../components/ErrorAlert.vue" import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb" diff --git a/app/frontend/src/views/Profile.vue b/app/frontend/src/views/Profile.vue index 51480a54e8..8f917bbe69 100644 --- a/app/frontend/src/views/Profile.vue +++ b/app/frontend/src/views/Profile.vue @@ -313,18 +313,18 @@ export default Vue.extend({ error: null as Error | null, HostingStatus, hostingStatusChoices: [ - { text: "(Leave blank)", value: 1 }, - { text: "Can host", value: 2 }, - { text: "Maybe", value: 3 }, - { text: "Difficult", value: 4 }, - { text: "Can't host", value: 5 }, + { text: "", value: HostingStatus.HOSTING_STATUS_UNKNOWN }, + { text: "Can host", value: HostingStatus.HOSTING_STATUS_CAN_HOST }, + { text: "Maybe", value: HostingStatus.HOSTING_STATUS_MAYBE }, + { text: "Difficult", value: HostingStatus.HOSTING_STATUS_DIFFICULT }, + { text: "Can't host", value: HostingStatus.HOSTING_STATUS_CANT_HOST }, ], smokingAllowedChoices: [ - { text: "", value: 1 }, - { text: "Yes", value: 2 }, - { text: "Window", value: 3 }, - { text: "Outside", value: 4 }, - { text: "No", value: 5 }, + { text: "", value: SmokingLocation.SMOKING_LOCATION_UNKNOWN }, + { text: "Yes", value: SmokingLocation.SMOKING_LOCATION_YES }, + { text: "Window", value: SmokingLocation.SMOKING_LOCATION_WINDOW }, + { text: "Outside", value: SmokingLocation.SMOKING_LOCATION_OUTSIDE }, + { text: "No", value: SmokingLocation.SMOKING_LOCATION_NO }, ], boolChoices: [ { text: "", value: null }, diff --git a/app/frontend/yarn.lock b/app/frontend/yarn.lock index f4c6b82ed1..b294830837 100644 --- a/app/frontend/yarn.lock +++ b/app/frontend/yarn.lock @@ -916,6 +916,24 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== +"@types/linkify-it@*": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-2.1.0.tgz#ea3dd64c4805597311790b61e872cbd1ed2cd806" + integrity sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw== + +"@types/markdown-it@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-10.0.2.tgz#f93334b9c7821ddb19865dfd91ecf688094c2626" + integrity sha512-FGKiVW1UgeIEAChYAuHcfCd0W4LsMEyrSyTVaZiuJhwR4BwSVUD8JKnzmWAMK2FHNLZSPGUaEkpa/dkZj2uq1w== + dependencies: + "@types/linkify-it" "*" + "@types/mdurl" "*" + +"@types/mdurl@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" + integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -3213,7 +3231,7 @@ entities@^1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -entities@^2.0.0: +entities@^2.0.0, entities@~2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== @@ -3945,11 +3963,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -github-markdown-css@^2.8.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-2.10.0.tgz#0612fed22816b33b282f37ef8def7a4ecabfe993" - integrity sha512-RX5VUC54uX6Lvrm226M9kMzsNeOa81MnKyxb3J0G5KLjyoOySOZgwyKFkUpv6iUhooiUZdogk+OTwQPJ4WttYg== - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -4174,11 +4187,6 @@ highlight.js@^9.6.0: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.1.tgz#ed21aa001fe6252bb10a3d76d47573c6539fe13c" integrity sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg== -highlightjs@^9.10.0: - version "9.16.2" - resolved "https://registry.yarnpkg.com/highlightjs/-/highlightjs-9.16.2.tgz#07ea6cc7c93340fc440734fb7abf28558f1f0fe1" - integrity sha512-FK1vmMj8BbEipEy8DLIvp71t5UsC7n2D6En/UfM/91PCwmOpj6f2iu0Y0coRC62KSRHHC+dquM2xMULV/X7NFg== - hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -5016,6 +5024,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +linkify-it@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + loader-fs-cache@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz#f08657646d607078be2f0a032f8bd69dd6f277d9" @@ -5083,11 +5098,6 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.toarray@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" - integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= - lodash.transform@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.transform/-/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0" @@ -5169,6 +5179,17 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" + integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== + dependencies: + argparse "^1.0.7" + entities "~2.0.0" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -5188,6 +5209,11 @@ mdn-data@2.0.6: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -5507,13 +5533,6 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-emoji@^1.8.1: - version "1.10.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" - integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw== - dependencies: - lodash.toarray "^4.4.0" - node-forge@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" @@ -7913,6 +7932,11 @@ typescript@~3.9.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + uglify-js@3.4.x: version "3.4.10" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" @@ -8195,15 +8219,6 @@ vue-router@^3.2.0: resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.3.4.tgz#4e38abc34a11c41b6c3d8244449a2e363ba6250b" integrity sha512-SdKRBeoXUjaZ9R/8AyxsdTqkOfMcI5tWxPZOUX5Ie1BTL5rPSZ0O++pbiZCeYeythiZIdLEfkDiQPKIaWk5hDg== -vue-simple-markdown@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/vue-simple-markdown/-/vue-simple-markdown-1.1.4.tgz#a34ac57e18746953b8c27089d5165941fe65cbd9" - integrity sha512-J6q9lqkOoOsBNYiKcqeXet2EDKtYLURNxnm4wMJa/Pknn953pP6FYiu40sD1j1HEG86+rxgOXFL0DplseWcjOA== - dependencies: - github-markdown-css "^2.8.0" - highlightjs "^9.10.0" - node-emoji "^1.8.1" - vue-style-loader@^4.1.0, vue-style-loader@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8" diff --git a/app/pb/auth.proto b/app/pb/auth.proto index 8a45bc4792..0ec44f1efc 100644 --- a/app/pb/auth.proto +++ b/app/pb/auth.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package org.couchers.auth; +import "pb/api.proto"; + service Auth { /* Authentication API @@ -98,6 +100,7 @@ message CompleteSignupReq { string city = 4; string birthdate = 5; // in YYYY-MM-DD format string gender = 6; + org.couchers.api.core.HostingStatus hosting_status = 7; } message LoginReq {