diff --git a/src/components/CommunityComponents/CommunityHamburger.vue b/src/components/CommunityComponents/CommunityHamburger.vue index 7754ce6eb97658c51124f5bd2b476e6b14a32c0e..d788a57adb429e7aeb3af5cbd9f1c10f35ff6a8d 100644 --- a/src/components/CommunityComponents/CommunityHamburger.vue +++ b/src/components/CommunityComponents/CommunityHamburger.vue @@ -39,7 +39,6 @@ <script> import { LeaveCommunity } from "@/utils/apiutil"; -import CommunityAdminService from "@/services/community-admin.service"; export default { name: "CommunityHamburger", @@ -57,13 +56,12 @@ export default { this.$router.push("/"); }, }, - async mounted() { - this.admin = await CommunityAdminService.isUserAdmin( - this.$route.params.communityID - ); - }, created() { this.communityID = this.$route.params.communityID; + if (!Array.isArray(this.$store.state.user.adminList)) return; + this.admin = this.$store.state.user.adminList.includes( + parseInt(this.communityID) + ); }, }; </script> diff --git a/src/components/UserAuthComponents/LoginForm.vue b/src/components/UserAuthComponents/LoginForm.vue index 4b52c2efef1be63592ab7843f55bcf7a945f4e0d..f13178ceae8c28771bb0e46fc12ffccc98605e81 100644 --- a/src/components/UserAuthComponents/LoginForm.vue +++ b/src/components/UserAuthComponents/LoginForm.vue @@ -94,6 +94,7 @@ import useVuelidate from "@vuelidate/core"; import { required, email, helpers } from "@vuelidate/validators"; import { doLogin } from "@/utils/apiutil"; import Button from "@/components/BaseComponents/ColoredButton"; +import UserService from "@/services/user.service"; export default { name: "LoginForm.vue", @@ -151,6 +152,8 @@ export default { this.message = "Feil e-post/passord"; } else if (loginResponse.isLoggedIn === true) { this.$store.commit("saveToken", loginResponse.token); + const adminList = await UserService.getAdminList(); + this.$store.commit("addAdminList", adminList); await this.$router.push("/"); } }, diff --git a/src/components/UserAuthComponents/RegisterForm.vue b/src/components/UserAuthComponents/RegisterForm.vue index 17cd3cf736afe4e9a3c53d30af6527e7a3d8602a..da8011bdce8f479730d0e8e16b082a09842243ba 100644 --- a/src/components/UserAuthComponents/RegisterForm.vue +++ b/src/components/UserAuthComponents/RegisterForm.vue @@ -175,6 +175,7 @@ import { helpers, } from "@vuelidate/validators"; import Button from "@/components/BaseComponents/ColoredButton"; +import UserService from "@/services/user.service"; // const isEmailTaken = (value) => // fetch(`/api/unique/${value}`).then((r) => r.json()); // check the email in the server @@ -263,8 +264,9 @@ export default { await this.$router.push("/login"); return; } - this.$store.commit("saveToken", loginResponse.token); + const adminList = await UserService.getAdminList(); + this.$store.commit("addAdminList", adminList); await this.$router.push("/"); }, async sendRegisterRequest() { diff --git a/src/components/UserProfileComponents/UserProfile.vue b/src/components/UserProfileComponents/UserProfile.vue index 6d401940bc4c7f395afe6b7878ff21d9c8cdadec..e560c29397d25006cf39aeb5010d5eba2b1484c7 100644 --- a/src/components/UserProfileComponents/UserProfile.vue +++ b/src/components/UserProfileComponents/UserProfile.vue @@ -140,6 +140,9 @@ export default { } return this.profileImage.src; }, + adminList() { + return this.$store.state.user.adminList; + }, }, methods: { async getUser() { diff --git a/src/router/index.js b/src/router/index.js index 3a6d7a8316d3c5d61ea2a1d614d65f15f74072c9..9e0d226d63d88e2b70bc49fe69ea4097ab56ef3e 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -15,6 +15,12 @@ function guardRoute(to, from, next) { } } +function isAdmin(to, from, next) { + if (store.state.user.adminList.includes(parseInt(from.params.communityID))) + next(); + else next("/"); +} + const routes = [ { path: "/", @@ -114,7 +120,7 @@ const routes = [ path: "/community/:communityID/admin", name: "CommunityAdminView", component: () => import("@/views/CommunityViews/AdminView.vue"), - beforeEnter: guardRoute, + beforeEnter: isAdmin, }, { path: "/itempage/:id", diff --git a/src/services/user.service.js b/src/services/user.service.js index dbbe29680b64ea39e9f8f262fc24eb4958dc1dd2..8bb44b7190a718b5a013467e3642107664cd194e 100644 --- a/src/services/user.service.js +++ b/src/services/user.service.js @@ -15,6 +15,19 @@ class UserService { .catch((err) => console.error(err)); } + async getAdminList() { + return await axios + .get(API_URL + "communities/admin", { + headers: tokenHeader(), + }) + .then((res) => { + return res.data; + }) + .catch((err) => { + console.error(err); + }); + } + async getUserRatingAverage(userId) { return await axios .get(API_URL + "rating/" + userId + "/average", { @@ -29,14 +42,14 @@ class UserService { async setListingToDeleted(listingId) { return await axios .delete(API_URL + "listing/" + listingId, { - headers: tokenHeader() + headers: tokenHeader(), }) .then((res) => { return res.data; }) .catch((err) => { - console.error(err); - }) + console.error(err); + }); } async getRenterHistory() { diff --git a/src/store/modules/user.js b/src/store/modules/user.js index c4ce2e515e6d57453551ba3c6d80e6376441ab6b..8c3744e58a0c4e387ddb83cfcef1a99efebbff7d 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,5 +1,6 @@ const state = { token: null, + adminList: [], }; const mutations = { @@ -9,6 +10,14 @@ const mutations = { saveToken(state, token) { state.token = token; }, + addAdminList(state, communityIDArray) { + if (!Array.isArray(communityIDArray)) return; + if (communityIDArray.length === 0) return; + for (let i = 0; i < communityIDArray.length; i++) { + if (isNaN(communityIDArray[i])) continue; + state.adminList.push(communityIDArray[i]); + } + }, }; export default { diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/login-form.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/login-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..7d3875c13b81280752f1d753d824b2f830373fc9 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/login-form.spec.js.snap @@ -0,0 +1,77 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LoginForm component renders correctly 1`] = ` +<div + class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full" +> + <div + class="px-6 py-4 mt-4" + > + <div + class="text-xl md:text-2xl font-medium text-center text-primary-light mt-4 mb-8" + > + Logg på + </div> + <div> + <div + class="w-full mt-6" + > + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + placeholder="Skriv inn din e-postadresse *" + required="" + type="email" + /> + <!-- error message --> + + + </div> + <div + class="w-full mt-6" + > + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + placeholder="Vennligst oppgi passordet ditt *" + required="" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="flex items-center justify-between mt-8" + > + <router-link + class="text-primary-medium" + to="/resetPassword" + > + Glemt passord? + </router-link> + <button + class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light" + > + Logg på + </button> + </div> + </div> + </div> + <div + class="flex items-center justify-center py-4 text-center bg-gray-50 dark:bg-gray-700" + > + <router-link + class="mx-2 text-sm font-bold text-primary-medium dark:text-primary-light hover:underline" + to="/register" + > + Opprette ny konto + </router-link> + </div> + <div + class="flex items-center justify-center text-center bg-gray-50" + > + <label + class="mx-2 text-sm font-bold text-error-medium dark:text-primary-light hover:underline" + /> + </div> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/new-password-form.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/new-password-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..129085284ce0c40121b0be19e799ac65b7361f12 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/new-password-form.spec.js.snap @@ -0,0 +1,88 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NewPasswordForm component renders correctly 1`] = ` +<div + class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4" +> + <h3 + class="text-xl font-medium text-center text-gray-600 dark:text-gray-200 mt-4 mb-8" + > + Endre passord + </h3> + <div + class="" + id="oldPasswordField" + > + <label + class="block text-sm text-gray-800 dark:text-gray-200" + for="oldPassword" + > + Gammelt passord + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="mt-4" + id="firstPasswordField" + > + <label + class="block text-sm text-gray-800 dark:text-gray-200" + for="password" + > + Nytt passord + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="mt-4" + id="secondPasswordField" + > + <div + class="flex items-center justify-between" + > + <label + class="block text-sm text-gray-800 dark:text-gray-200" + for="rePassword" + > + Gjenta nytt passord + </label> + </div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300" + type="password" + /> + <!-- error message --> + + + </div> + <div + class="mt-6" + id="buttonsField" + > + <button + class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light float-right" + > + Sett ny passord + </button> + </div> + <div + class="flex items-center justify-center text-center bg-gray-50" + > + <label + class="mx-2 text-sm font-bold text-error-medium dark:text-primary-light hover:underline" + /> + </div> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/rating.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/rating.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..f22076edecd3620957e0bbf9141873adfd3a6322 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/rating.spec.js.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Rating component renders correctly 1`] = ` +<ul + class="flex justify-center" +> + <li> + <p + class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400" + > + : + </p> + </li> + <li> + <p + class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400" + > + Ingen vurderinger + </p> + </li> +</ul> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..8adae3ffa2833611c6e3da43443b7e2a381b4e3f --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/register-user-component.spec.js.snap @@ -0,0 +1,96 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RegisterFormComponent renders correctly 1`] = ` +<div + class="w-full max-w-md mx-auto mb-auto md:ring-1 ring-gray-300 overflow-hidden rounded-xl p-4" +> + <div + class="text-xl md:text-2xl font-medium text-center text-primary-light mt-4 mb-8" + id="registerLabel" + > + Opprett ny konto + </div> + <form> + <div + class="grid grid-cols-1 gap-6 mt-4" + > + <div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="email" + placeholder="E-post adresse" + type="email" + /> + <!-- error message --> + + + </div> + <div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="password" + placeholder="Passord" + type="password" + /> + <!-- error message --> + + + </div> + <div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="confirmPassword" + placeholder="Bekreft passord" + type="password" + /> + <!-- error message --> + + + </div> + <div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + data-test="firstNameTest" + id="firstName" + placeholder="Fornavn" + type="text" + /> + <!-- error message --> + + + </div> + <div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="lastName" + placeholder="Etternavn" + type="text" + /> + <!-- error message --> + + + </div> + <div> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light" + id="address" + placeholder="Adresse" + type="text" + /> + <!-- error message --> + + + </div> + </div> + <div + class="flex justify-end mt-6" + > + <button + class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light" + > + Opprett + </button> + </div> + </form> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/reset-password-form.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/reset-password-form.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..7b7c1ace2fabdd62b5a782799ce6d1f71ba8bfb1 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/reset-password-form.spec.js.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ResetPasswordForm component renders correctly 1`] = ` +<div + class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4" +> + <h3 + class="text-xl font-medium text-center text-primary-light mt-4 mb-8" + > + Glemt passordet ditt? + </h3> + <div + class="m-6" + id="emailField" + > + <div + class="mb-6" + > + <label + class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" + for="email" + > + E-post + </label> + <input + class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-blue-300" + id="email" + placeholder="eksempel@eksempel.no" + required="" + type="email" + /> + <!-- error message --> + + + </div> + <button + class="block text-white bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-light float-right" + > + Tilbakestill passord + </button> + </div> +</div> +`; diff --git a/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap b/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..db5d7bf26553750dd6c9f3789f9541ffc2d2f071 --- /dev/null +++ b/tests/unit/component-tests/user-component-tests/__snapshots__/user-items.spec.js.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UserItems component renders correctly 1`] = ` +<div + data-v-app="" +> + + <div + class="text-xl md:text-2xl text-primary-light font-medium" + id="headline" + > + Mine gjenstander + </div> + <!-- Search field --> + <div + class="relative" + id="searchComponent" + > + <span + class="absolute inset-y-0 left-0 flex items-center pl-3" + > + <svg + class="w-5 h-5 text-gray-400" + fill="none" + viewBox="0 0 24 24" + > + <path + d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" + stroke="currentColor" + stroke-linecap="round" + stroke-linejoin="round" + stroke-width="2" + /> + </svg> + </span> + <input + class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring" + id="searchInput" + placeholder="Search" + type="text" + /> + </div> + <div + class="absolute inset-x-0 px-5 py-3" + > + <!-- ItemCards --> + <div + class="flex items-center justify-center w-screen" + > + <!-- Shows items based on pagination --> + <div + class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full" + > + + + + <!-- Main modal --> + <!--v-if--> + + </div> + <!-- Shows items based on search field input --> + <!--v-if--> + </div> + <!-- pagination --> + <div + class="flex justify-center" + > + <div + class="mt-10" + > + <!--v-if--> + <label + class="mx-2 text-primary-light" + > + 1 av 1 + </label> + <!--v-if--> + </div> + </div> + </div> + +</div> +`;