Browse Source

refactor: Display user display names instead of usernames in links

Owen Diffey 3 years ago
parent
commit
7ff3026b2b

+ 8 - 51
backend/logic/actions/users.js

@@ -1,6 +1,7 @@
 import config from "config";
 
 import async from "async";
+import mongoose from "mongoose";
 
 import axios from "axios";
 import bcrypt from "bcrypt";
@@ -1559,19 +1560,20 @@ export default {
 	}),
 
 	/**
-	 * Gets user object from username (only a few properties)
+	 * Gets user object from ObjectId or username (only a few properties)
 	 *
 	 * @param {object} session - the session object automatically added by the websocket
-	 * @param {string} username - the username of the user we are trying to find
+	 * @param {string} identifier - the ObjectId or username of the user we are trying to find
 	 * @param {Function} cb - gets called with the result
 	 */
-	findByUsername: async function findByUsername(session, username, cb) {
+	getBasicUser: async function getBasicUser(session, identifier, cb) {
 		const userModel = await DBModule.runJob("GET_MODEL", { modelName: "user" }, this);
 
 		async.waterfall(
 			[
 				next => {
-					userModel.findOne({ username: new RegExp(`^${username}$`, "i") }, next);
+					if (mongoose.Types.ObjectId.isValid(identifier)) userModel.findOne({ _id: identifier }, next);
+					else userModel.findOne({ username: new RegExp(`^${identifier}$`, "i") }, next);
 				},
 
 				(account, next) => {
@@ -1583,12 +1585,12 @@ export default {
 				if (err && err !== true) {
 					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
 
-					this.log("ERROR", "FIND_BY_USERNAME", `User not found for username "${username}". "${err}"`);
+					this.log("ERROR", "GET_BASIC_USER", `User not found for "${identifier}". "${err}"`);
 
 					return cb({ status: "error", message: err });
 				}
 
-				this.log("SUCCESS", "FIND_BY_USERNAME", `User found for username "${username}".`);
+				this.log("SUCCESS", "GET_BASIC_USER", `User found for "${identifier}".`);
 
 				return cb({
 					status: "success",
@@ -1607,51 +1609,6 @@ export default {
 		);
 	},
 
-	/**
-	 * Gets a username from an userId
-	 *
-	 * @param {object} session - the session object automatically added by the websocket
-	 * @param {string} userId - the userId of the person we are trying to get the username from
-	 * @param {Function} cb - gets called with the result
-	 */
-	async getUsernameFromId(session, userId, cb) {
-		const userModel = await DBModule.runJob("GET_MODEL", { modelName: "user" }, this);
-		userModel
-			.findById(userId)
-			.then(user => {
-				if (user) {
-					this.log("SUCCESS", "GET_USERNAME_FROM_ID", `Found username for userId "${userId}".`);
-
-					return cb({
-						status: "success",
-						data: { username: user.username }
-					});
-				}
-
-				this.log(
-					"ERROR",
-					"GET_USERNAME_FROM_ID",
-					`Getting the username from userId "${userId}" failed. User not found.`
-				);
-
-				return cb({
-					status: "error",
-					message: "Couldn't find the user."
-				});
-			})
-			.catch(async err => {
-				if (err && err !== true) {
-					err = await UtilsModule.runJob("GET_ERROR", { error: err }, this);
-					this.log(
-						"ERROR",
-						"GET_USERNAME_FROM_ID",
-						`Getting the username from userId "${userId}" failed. "${err}"`
-					);
-					cb({ status: "error", message: err });
-				}
-			});
-	},
-
 	/**
 	 * Gets a user from a userId
 	 *

+ 1 - 5
frontend/src/components/PlaylistItem.vue

@@ -20,11 +20,7 @@
 						v-if="playlist.createdBy === 'Musare'"
 						:title="sitename"
 						>{{ sitename }}</a
-					><user-id-to-username
-						v-else
-						:user-id="playlist.createdBy"
-						:link="true"
-					/>
+					><user-link v-else :user-id="playlist.createdBy" />
 				</span>
 				<span :title="playlistLength">

+ 2 - 3
frontend/src/components/PunishmentItem.vue

@@ -15,10 +15,9 @@
 		<div class="item-title-description">
 			<h2 v-if="punishment.type === 'banUserId'" class="item-title">
 				<strong>Punishment</strong> for user
-				<user-id-to-username
+				<user-link
 					:user-id="punishment.value"
 					:alt="punishment.value"
-					:link="true"
 				/>
 			</h2>
 			<h2 class="item-title" v-else>
@@ -45,7 +44,7 @@
 				</li>
 				<li class="item-description">
 					Punished by
-					<user-id-to-username
+					<user-link
 						:user-id="punishment.punishedBy"
 						:alt="punishment.punishedBy"
 					/>

+ 1 - 2
frontend/src/components/SongItem.vue

@@ -40,11 +40,10 @@
 				<p class="song-request-time" v-if="requestedBy">
 					Requested by
 					<strong>
-						<user-id-to-username
+						<user-link
 							v-if="song.requestedBy"
 							:key="song._id"
 							:user-id="song.requestedBy"
-							:link="true"
 						/>
 						<span v-else>station</span>
 						{{ formatedRequestedAt }}

+ 0 - 46
frontend/src/components/global/UserIdToUsername.vue

@@ -1,46 +0,0 @@
-<template>
-	<router-link
-		v-if="$props.link && username !== 'unknown'"
-		:to="{ path: `/u/${username}` }"
-		:title="userId"
-	>
-		{{ username }}
-	</router-link>
-	<span :title="userId" v-else>
-		{{ username }}
-	</span>
-</template>
-
-<script>
-import { mapActions } from "vuex";
-
-export default {
-	props: {
-		userId: { type: String, default: "" },
-		link: Boolean
-	},
-	data() {
-		return {
-			username: "unknown"
-		};
-	},
-	mounted() {
-		this.getUsernameFromId(this.$props.userId).then(username => {
-			if (username) this.username = username;
-		});
-	},
-	methods: {
-		...mapActions("user/auth", ["getUsernameFromId"])
-	}
-};
-</script>
-
-<style lang="less" scoped>
-a {
-	color: var(--primary-color);
-	&:hover,
-	&:focus {
-		filter: brightness(90%);
-	}
-}
-</style>

+ 53 - 0
frontend/src/components/global/UserLink.vue

@@ -0,0 +1,53 @@
+<template>
+	<router-link
+		v-if="$props.link && user.username"
+		:to="{ path: `/u/${user.username}` }"
+		:title="userId"
+	>
+		{{ user.name }}
+	</router-link>
+	<span v-else :title="userId">
+		{{ user.name }}
+	</span>
+</template>
+
+<script>
+import { mapActions } from "vuex";
+
+export default {
+	props: {
+		userId: { type: String, default: "" },
+		link: { type: Boolean, default: true }
+	},
+	data() {
+		return {
+			user: {
+				name: "Unknown",
+				username: null
+			}
+		};
+	},
+	mounted() {
+		this.getBasicUser(this.$props.userId).then(user => {
+			if (user)
+				this.user = {
+					name: user.name,
+					username: user.username
+				};
+		});
+	},
+	methods: {
+		...mapActions("user/auth", ["getBasicUser"])
+	}
+};
+</script>
+
+<style lang="less" scoped>
+a {
+	color: var(--primary-color);
+	&:hover,
+	&:focus {
+		filter: brightness(90%);
+	}
+}
+</style>

+ 1 - 2
frontend/src/components/modals/EditNews.vue

@@ -57,10 +57,9 @@
 				<div class="right" v-if="createdAt > 0">
 					<span>
 						By
-						<user-id-to-username
+						<user-link
 							:user-id="createdBy"
 							:alt="createdBy"
-							:link="true"
 						/> </span
 					>&nbsp;<span :title="new Date(createdAt)">
 						{{

+ 2 - 3
frontend/src/components/modals/WhatIsNew.vue

@@ -9,10 +9,9 @@
 		<template #footer>
 			<span v-if="news.createdBy">
 				By
-				<user-id-to-username
+				<user-link
 					:user-id="news.createdBy"
-					:alt="news.createdBy"
-					:link="true" /></span
+					:alt="news.createdBy" /></span
 			>&nbsp;<span :title="new Date(news.createdAt)">
 				{{
 					formatDistance(news.createdAt, new Date(), {

+ 1 - 2
frontend/src/pages/Admin/News.vue

@@ -69,10 +69,9 @@
 					}}</span>
 				</template>
 				<template #column-createdBy="slotProps">
-					<user-id-to-username
+					<user-link
 						:user-id="slotProps.item.createdBy"
 						:alt="slotProps.item.createdBy"
-						:link="true"
 					/>
 				</template>
 				<template #column-markdown="slotProps">

+ 1 - 5
frontend/src/pages/Admin/Playlists.vue

@@ -60,11 +60,7 @@
 					<span v-if="slotProps.item.createdBy === 'Musare'"
 						>Musare</span
 					>
-					<user-id-to-username
-						v-else
-						:user-id="slotProps.item.createdBy"
-						:link="true"
-					/>
+					<user-link v-else :user-id="slotProps.item.createdBy" />
 				</template>
 				<template #column-createdAt="slotProps">
 					<span :title="new Date(slotProps.item.createdAt)">{{

+ 2 - 6
frontend/src/pages/Admin/Punishments.vue

@@ -46,11 +46,10 @@
 					>
 				</template>
 				<template #column-value="slotProps">
-					<user-id-to-username
+					<user-link
 						v-if="slotProps.item.type === 'banUserId'"
 						:user-id="slotProps.item.value"
 						:alt="slotProps.item.value"
-						:link="true"
 					/>
 					<span v-else :title="slotProps.item.value">{{
 						slotProps.item.value
@@ -62,10 +61,7 @@
 					}}</span>
 				</template>
 				<template #column-punishedBy="slotProps">
-					<user-id-to-username
-						:user-id="slotProps.item.punishedBy"
-						:link="true"
-					/>
+					<user-link :user-id="slotProps.item.punishedBy" />
 				</template>
 				<template #column-punishedAt="slotProps">
 					<span :title="new Date(slotProps.item.punishedAt)">{{

+ 1 - 5
frontend/src/pages/Admin/Reports.vue

@@ -93,11 +93,7 @@
 					<span v-if="slotProps.item.createdBy === 'Musare'"
 						>Musare</span
 					>
-					<user-id-to-username
-						v-else
-						:user-id="slotProps.item.createdBy"
-						:link="true"
-					/>
+					<user-link v-else :user-id="slotProps.item.createdBy" />
 				</template>
 				<template #column-createdAt="slotProps">
 					<span :title="new Date(slotProps.item.createdAt)">{{

+ 2 - 8
frontend/src/pages/Admin/Songs.vue

@@ -155,10 +155,7 @@
 					}}</span>
 				</template>
 				<template #column-requestedBy="slotProps">
-					<user-id-to-username
-						:user-id="slotProps.item.requestedBy"
-						:link="true"
-					/>
+					<user-link :user-id="slotProps.item.requestedBy" />
 				</template>
 				<template #column-requestedAt="slotProps">
 					<span :title="new Date(slotProps.item.requestedAt)">{{
@@ -166,10 +163,7 @@
 					}}</span>
 				</template>
 				<template #column-verifiedBy="slotProps">
-					<user-id-to-username
-						:user-id="slotProps.item.verifiedBy"
-						:link="true"
-					/>
+					<user-link :user-id="slotProps.item.verifiedBy" />
 				</template>
 				<template #column-verifiedAt="slotProps">
 					<span :title="new Date(slotProps.item.verifiedAt)">{{

+ 1 - 5
frontend/src/pages/Admin/Stations.vue

@@ -101,11 +101,7 @@
 					<span v-if="slotProps.item.type === 'official'"
 						>Musare</span
 					>
-					<user-id-to-username
-						v-else
-						:user-id="slotProps.item.owner"
-						:link="true"
-					/>
+					<user-link v-else :user-id="slotProps.item.owner" />
 				</template>
 				<template #column-theme="slotProps">
 					<span :title="slotProps.item.theme">{{

+ 2 - 4
frontend/src/pages/Home.vue

@@ -168,10 +168,9 @@
 														siteSettings.sitename
 													}}</span
 												>
-												<user-id-to-username
+												<user-link
 													v-else
 													:user-id="element.owner"
-													:link="true"
 												/>
 											</span>
 										</p>
@@ -418,10 +417,9 @@
 											:title="siteSettings.sitename"
 											>{{ siteSettings.sitename }}</span
 										>
-										<user-id-to-username
+										<user-link
 											v-else
 											:user-id="station.owner"
-											:link="true"
 										/>
 									</span>
 								</p>

+ 1 - 2
frontend/src/pages/News.vue

@@ -14,10 +14,9 @@
 					<div class="info">
 						<hr />
 						By
-						<user-id-to-username
+						<user-link
 							:user-id="item.createdBy"
 							:alt="item.createdBy"
-							:link="true"
 						/>&nbsp;<span :title="new Date(item.createdAt)">
 							{{
 								formatDistance(item.createdAt, new Date(), {

+ 3 - 3
frontend/src/pages/Profile/Tabs/RecentActivity.vue

@@ -109,8 +109,8 @@ export default {
 	methods: {
 		init() {
 			if (this.myUserId !== this.userId)
-				this.getUsernameFromId(this.userId).then(username => {
-					if (username) this.username = username;
+				this.getBasicUser(this.userId).then(user => {
+					if (user && user.username) this.username = user.username;
 				});
 
 			this.socket.dispatch("activities.length", this.userId, res => {
@@ -154,7 +154,7 @@ export default {
 
 			return this.maxPosition === this.position;
 		},
-		...mapActions("user/auth", ["getUsernameFromId"])
+		...mapActions("user/auth", ["getBasicUser"])
 	}
 };
 </script>

+ 1 - 1
frontend/src/pages/Profile/index.vue

@@ -148,7 +148,7 @@ export default {
 	methods: {
 		init() {
 			this.socket.dispatch(
-				"users.findByUsername",
+				"users.getBasicUser",
 				this.$route.params.username,
 				res => {
 					if (res.status === "error") this.$router.push("/404");

+ 9 - 9
frontend/src/store/modules/user.js

@@ -105,38 +105,38 @@ const modules = {
 						.then(() => resolve())
 						.catch(() => reject());
 				}),
-			getUsernameFromId: ({ commit, state }, userId) =>
+			getBasicUser: ({ commit, state }, userId) =>
 				new Promise(resolve => {
 					if (typeof state.userIdMap[`Z${userId}`] !== "string") {
 						if (state.userIdRequested[`Z${userId}`] !== true) {
 							commit("requestingUserId", userId);
 							ws.socket.dispatch(
-								"users.getUsernameFromId",
+								"users.getBasicUser",
 								userId,
 								res => {
 									if (res.status === "success") {
-										const { username } = res.data;
+										const user = res.data;
 
 										commit("mapUserId", {
 											userId,
-											username
+											user
 										});
 
 										state.pendingUserIdCallbacks[
 											`Z${userId}`
-										].forEach(cb => cb(username));
+										].forEach(cb => cb(user));
 
 										commit("clearPendingCallbacks", userId);
 
-										return resolve(username);
+										return resolve(user);
 									}
 									return resolve();
 								}
 							);
 						} else {
-							commit("pendingUsername", {
+							commit("pendingUser", {
 								userId,
-								callback: username => resolve(username)
+								callback: user => resolve(user)
 							});
 						}
 					} else {
@@ -163,7 +163,7 @@ const modules = {
 				if (!state.pendingUserIdCallbacks[`Z${userId}`])
 					state.pendingUserIdCallbacks[`Z${userId}`] = [];
 			},
-			pendingUsername(state, data) {
+			pendingUser(state, data) {
 				state.pendingUserIdCallbacks[`Z${data.userId}`].push(
 					data.callback
 				);