3 Commits 9351694d55 ... 61142ef2ce

Author SHA1 Message Date
  Owen Diffey 61142ef2ce refactor: Remove set password functionality 3 weeks ago
  Owen Diffey fb26083539 refactor: Remove GitHub authentication 3 weeks ago
  Owen Diffey 8b0d302b04 refactor: Remove recaptcha 3 weeks ago

+ 0 - 7
.wiki/Configuration.md

@@ -89,13 +89,6 @@ For more information on configuration files please refer to the
 | `apis.soundcloud.rateLimit` | Minimum interval between SoundCloud API requests in milliseconds. |
 | `apis.soundcloud.requestTimeout` | SoundCloud API requests timeout in milliseconds. |
 | `apis.soundcloud.retryAmount` | The amount of retries to perform of a failed SoundCloud API request. |
-| `apis.recaptcha.enabled` | Whether to enable ReCaptcha in the regular (email) registration form. |
-| `apis.recaptcha.key` | ReCaptcha Site v3 key, obtained from [here](https://www.google.com/recaptcha/admin). |
-| `apis.recaptcha.secret` | ReCaptcha Site v3 secret, obtained with key. |
-| `apis.github.enabled` | Whether to enable GitHub authentication. |
-| `apis.github.client` | GitHub OAuth Application client, obtained from [here](https://github.com/settings/developers). |
-| `apis.github.secret` | GitHub OAuth Application secret, obtained with client. |
-| `apis.github.redirect_uri` | The backend url with `/auth/github/authorize/callback` appended, for example `http://localhost/backend/auth/github/authorize/callback`. This is configured based on the `url` config option by default. |
 | `apis.discogs.enabled` | Whether to enable Discogs API usage. |
 | `apis.discogs.client` | Discogs Application client, obtained from [here](https://www.discogs.com/settings/developers). |
 | `apis.discogs.secret` | Discogs Application secret, obtained with client. |

+ 1 - 1
README.md

@@ -71,7 +71,7 @@ A production demonstration instance of Musare can be found at [demo.musare.com](
   - Activity logs
   - Profile page showing public playlists and activity logs
   - Text or gravatar profile pictures
-  - Email or Github login/registration
+  - Password login/registration
   - Preferences to tailor site usage
   - Password reset
   - Data deletion management

+ 0 - 11
backend/config/default.json

@@ -47,17 +47,6 @@
 			"requestTimeout": 5000,
 			"retryAmount": 2
 		},
-		"recaptcha": {
-			"enabled": false,
-			"key": "",
-			"secret": ""
-		},
-		"github": {
-			"enabled": false,
-			"client": "",
-			"secret": "",
-			"redirect_uri": ""
-		},
 		"discogs": {
 			"enabled": false,
 			"client": "",

+ 0 - 8
backend/src/modules/DataModule/migrations/1725485641-create-users-table.ts

@@ -72,14 +72,6 @@ export const up = async ({
 			type: DataTypes.DATE,
 			allowNull: true
 		},
-		githubId: {
-			type: DataTypes.BIGINT,
-			allowNull: true
-		},
-		githubAccessToken: {
-			type: DataTypes.STRING,
-			allowNull: true
-		},
 		songsRequested: {
 			type: DataTypes.BIGINT,
 			allowNull: false,

+ 0 - 12
backend/src/modules/DataModule/models/User.ts

@@ -59,9 +59,6 @@ export class User extends Model<
 
 	declare passwordSetExpiresAt: CreationOptional<Date | null>;
 
-	declare githubId: CreationOptional<number | null>;
-
-	declare githubAccessToken: CreationOptional<string | null>;
 	// End services
 
 	// Statistics
@@ -222,14 +219,6 @@ export const schema = {
 		type: DataTypes.DATE,
 		allowNull: true
 	},
-	githubId: {
-		type: DataTypes.BIGINT,
-		allowNull: true
-	},
-	githubAccessToken: {
-		type: DataTypes.STRING,
-		allowNull: true
-	},
 	songsRequested: {
 		type: DataTypes.BIGINT,
 		allowNull: false,
@@ -301,7 +290,6 @@ export const options = {
 				"password",
 				"passwordResetCode",
 				"passwordSetCode",
-				"githubAccessToken"
 			]
 		}
 	}

+ 0 - 1
backend/src/modules/DataModule/models/User/getData.ts

@@ -6,7 +6,6 @@ export default {
 		"services.password.reset.expires",
 		"services.password.set.code",
 		"services.password.set.expires",
-		"services.github.access_token",
 		"email.verificationToken"
 	],
 	specialProperties: {

+ 0 - 5
backend/src/modules/WebSocketModule.ts

@@ -177,11 +177,6 @@ export class WebSocketModule extends BaseModule {
 			config: {
 				cookie: config.get("cookie"),
 				sitename: config.get("sitename"),
-				recaptcha: {
-					enabled: config.get("apis.recaptcha.enabled"),
-					key: config.get("apis.recaptcha.key")
-				},
-				githubAuthentication: config.get("apis.github.enabled"),
 				messages: config.get("messages"),
 				christmas: config.get("christmas"),
 				footerLinks: config.get("footerLinks"),

+ 0 - 1
frontend/.eslintrc

@@ -26,7 +26,6 @@
 		"@typescript-eslint"
 	],
 	"globals": {
-		"grecaptcha": "readonly",
 		"history": "readonly"
 	},
 	"rules": {

+ 0 - 13
frontend/src/App.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { useRouter } from "vue-router";
 import { defineAsyncComponent, ref, watch, onMounted } from "vue";
 import Toast from "toasters";
 import { storeToRefs } from "pinia";
@@ -22,8 +21,6 @@ const FallingSnow = defineAsyncComponent(
 	() => import("@/components/FallingSnow.vue")
 );
 
-const router = useRouter();
-
 const { socket } = useWebsocketsStore();
 const configStore = useConfigStore();
 const userAuthStore = useUserAuthStore();
@@ -165,16 +162,6 @@ onMounted(async () => {
 		});
 
 		openModal("whatIsNew");
-
-		router.isReady().then(() => {
-			if (
-				configStore.githubAuthentication &&
-				localStorage.getItem("github_redirect")
-			) {
-				router.push(localStorage.getItem("github_redirect"));
-				localStorage.removeItem("github_redirect");
-			}
-		});
 	});
 
 	socket.onDisconnect(() => {

+ 1 - 31
frontend/src/components/modals/Login.vue

@@ -21,7 +21,7 @@ const passwordVisible = ref(false);
 const passwordElement = ref();
 
 const configStore = useConfigStore();
-const { githubAuthentication, registrationDisabled } = storeToRefs(configStore);
+const { registrationDisabled } = storeToRefs(configStore);
 const { login } = useUserAuthStore();
 
 const { openModal, closeCurrentModal } = useModalsStore();
@@ -80,10 +80,6 @@ const changeToRegisterModal = () => {
 	closeCurrentModal();
 	openModal("register");
 };
-
-const githubRedirect = () => {
-	localStorage.setItem("github_redirect", route.path);
-};
 </script>
 
 <template>
@@ -168,20 +164,6 @@ const githubRedirect = () => {
 					<button class="button is-primary" @click="submitModal()">
 						Login
 					</button>
-					<a
-						v-if="githubAuthentication"
-						class="button is-github"
-						:href="configStore.urls.api + '/auth/github/authorize'"
-						@click="githubRedirect()"
-					>
-						<div class="icon">
-							<img
-								class="invert"
-								src="/assets/social/github.svg"
-							/>
-						</div>
-						&nbsp;&nbsp;Login with GitHub
-					</a>
 				</div>
 
 				<p
@@ -222,18 +204,6 @@ const githubRedirect = () => {
 	}
 }
 
-.button.is-github {
-	background-color: var(--dark-grey-2);
-	color: var(--white) !important;
-}
-
-.is-github:focus {
-	background-color: var(--dark-grey-4);
-}
-.is-primary:focus {
-	background-color: var(--primary-color) !important;
-}
-
 .invert {
 	filter: brightness(5);
 }

+ 1 - 62
frontend/src/components/modals/Register.vue

@@ -35,14 +35,12 @@ const password = ref({
 	message:
 		"Include at least one lowercase letter, one uppercase letter, one number and one special character."
 });
-const recaptchaToken = ref("");
 const passwordElement = ref();
 
 const { register } = useUserAuthStore();
 
 const configStore = useConfigStore();
-const { registrationDisabled, recaptcha, githubAuthentication } =
-	storeToRefs(configStore);
+const { registrationDisabled } = storeToRefs(configStore);
 const { openModal, closeCurrentModal } = useModalsStore();
 
 const submitModal = () => {
@@ -53,7 +51,6 @@ const submitModal = () => {
 		username: username.value.value,
 		email: email.value.value,
 		password: password.value.value,
-		recaptchaToken: recaptchaToken.value
 	})
 		.then((res: any) => {
 			if (res.status === "success") window.location.reload();
@@ -76,10 +73,6 @@ const changeToLoginModal = () => {
 	openModal("login");
 };
 
-const githubRedirect = () => {
-	localStorage.setItem("github_redirect", route.path);
-};
-
 watch(
 	() => username.value.value,
 	value => {
@@ -146,27 +139,6 @@ onMounted(async () => {
 		new Toast("Registration is disabled.");
 		closeCurrentModal();
 	}
-
-	if (recaptcha.value.enabled) {
-		const recaptchaScript = document.createElement("script");
-		recaptchaScript.onload = () => {
-			grecaptcha.ready(() => {
-				grecaptcha
-					.execute(recaptcha.value.key, {
-						action: "login"
-					})
-					.then(token => {
-						recaptchaToken.value = token;
-					});
-			});
-		};
-
-		recaptchaScript.setAttribute(
-			"src",
-			`https://www.google.com/recaptcha/api.js?render=${recaptcha.value.key}`
-		);
-		document.head.appendChild(recaptchaScript);
-	}
 });
 </script>
 
@@ -274,20 +246,6 @@ onMounted(async () => {
 					<button class="button is-primary" @click="submitModal()">
 						Register
 					</button>
-					<a
-						v-if="githubAuthentication"
-						class="button is-github"
-						:href="configStore.urls.api + '/auth/github/authorize'"
-						@click="githubRedirect()"
-					>
-						<div class="icon">
-							<img
-								class="invert"
-								src="/assets/social/github.svg"
-							/>
-						</div>
-						&nbsp;&nbsp;Register with GitHub
-					</a>
 				</div>
 
 				<p class="content-box-optional-helper">
@@ -329,30 +287,11 @@ onMounted(async () => {
 	}
 }
 
-.button.is-github {
-	background-color: var(--dark-grey-2);
-	color: var(--white) !important;
-}
-
-.is-github:focus {
-	background-color: var(--dark-grey-4);
-}
-
 .invert {
 	filter: brightness(5);
 }
 
-#recaptcha {
-	padding: 10px 0;
-}
-
 a {
 	color: var(--primary-color);
 }
 </style>
-
-<style lang="less">
-.grecaptcha-badge {
-	z-index: 2000;
-}
-</style>

+ 0 - 9
frontend/src/main.ts

@@ -149,15 +149,6 @@ const router = createRouter({
 				configRequired: "mailEnabled"
 			}
 		},
-		{
-			path: "/set_password",
-			props: { mode: "set" },
-			component: () => import("@/pages/ResetPassword.vue"),
-			meta: {
-				configRequired: "mailEnabled",
-				loginRequired: true
-			}
-		},
 		{
 			path: "/admin",
 			name: "admin",

+ 0 - 22
frontend/src/pages/Admin/Users/index.vue

@@ -63,14 +63,6 @@ const columns = ref<TableColumn[]>([
 		minWidth: 230,
 		defaultWidth: 230
 	},
-	{
-		name: "githubId",
-		displayName: "GitHub ID",
-		properties: ["githubId"],
-		sortProperty: "githubId",
-		minWidth: 115,
-		defaultWidth: 115
-	},
 	{
 		name: "hasPassword",
 		displayName: "Has Password",
@@ -132,13 +124,6 @@ const filters = ref<TableFilter[]>([
 		filterTypes: ["contains", "exact", "regex"],
 		defaultFilterType: "contains"
 	},
-	{
-		name: "githubId",
-		displayName: "GitHub ID",
-		property: "services.github.id",
-		filterTypes: ["contains", "exact", "regex"],
-		defaultFilterType: "contains"
-	},
 	{
 		name: "hasPassword",
 		displayName: "Has Password",
@@ -268,13 +253,6 @@ onMounted(() => {
 					slotProps.item._id
 				}}</span>
 			</template>
-			<template #column-githubId="slotProps">
-				<span
-					v-if="slotProps.item.githubId"
-					:title="slotProps.item.githubId"
-					>{{ slotProps.item.githubId }}</span
-				>
-			</template>
 			<template #column-hasPassword="slotProps">
 				<span :title="slotProps.item.hasPassword">{{
 					slotProps.item.hasPassword

+ 4 - 5
frontend/src/pages/Privacy.vue

@@ -34,11 +34,10 @@ const MainFooter = defineAsyncComponent(
 				address, mailing address, phone number, photo, username from
 				other social media sites, gender, date of birth, or other
 				relevant information. In addition, we utilize third party API’s
-				like GitHub Authentication, and other API’s that allow you to
-				transfer your profile information from those Sites to ours
-				depending on your settings on those Sites. We are not
-				responsible for any information that does not transfer or if any
-				information is inaccurate.
+				that allow you to transfer your profile information from those
+				Sites to ours depending on your settings on those Sites. We are
+				not responsible for any information that does not transfer or if
+				any information is inaccurate.
 			</p>
 
 			<p>

+ 6 - 23
frontend/src/pages/ResetPassword.vue

@@ -16,10 +16,6 @@ const InputHelpBox = defineAsyncComponent(
 	() => import("@/components/InputHelpBox.vue")
 );
 
-const props = defineProps({
-	mode: { type: String, enum: ["reset", "set"], default: "reset" }
-});
-
 const userAuthStore = useUserAuthStore();
 const { currentUser } = storeToRefs(userAuthStore);
 
@@ -89,13 +85,6 @@ const submitEmail = () => {
 
 	inputs.value.email.hasBeenSentAlready = false;
 
-	if (props.mode === "set") {
-		return socket.dispatch("users.requestPassword", res => {
-			new Toast(res.message);
-			if (res.status === "success") step.value = 2;
-		});
-	}
-
 	return socket.dispatch(
 		"users.requestPasswordReset",
 		inputs.value.email.value,
@@ -113,9 +102,7 @@ const verifyCode = () => {
 	if (!code.value) return new Toast("Code cannot be empty");
 
 	return socket.dispatch(
-		props.mode === "set"
-			? "users.verifyPasswordCode"
-			: "users.verifyPasswordResetCode",
+		"users.verifyPasswordResetCode",
 		code.value,
 		res => {
 			new Toast(res.message);
@@ -132,9 +119,7 @@ const changePassword = () => {
 		return new Toast("Please enter a valid password.");
 
 	return socket.dispatch(
-		props.mode === "set"
-			? "users.changePasswordWithCode"
-			: "users.changePasswordWithResetCode",
+		"users.changePasswordWithResetCode",
 		code.value,
 		inputs.value.password.value,
 		res => {
@@ -199,14 +184,12 @@ onMounted(() => {
 
 <template>
 	<div>
-		<page-metadata
-			:title="mode === 'reset' ? 'Reset password' : 'Set password'"
-		/>
+		<page-metadata title="Reset password" />
 		<main-header />
 		<div class="container">
 			<div class="content-wrapper">
 				<h1 id="title" class="has-text-centered page-title">
-					{{ mode === "reset" ? "Reset" : "Set" }} your password
+					Reset your password
 				</h1>
 
 				<div id="steps">
@@ -466,7 +449,7 @@ onMounted(() => {
 								<i class="material-icons success-icon"
 									>check_circle</i
 								>
-								<h2>Password successfully {{ mode }}</h2>
+								<h2>Password successfully reset</h2>
 								<router-link
 									class="button is-dark"
 									to="/settings"
@@ -483,7 +466,7 @@ onMounted(() => {
 							>
 								<i class="material-icons error-icon">error</i>
 								<h2>
-									Password {{ mode }} failed, please try again
+									Password reset failed, please try again
 									later
 								</h2>
 								<router-link

+ 2 - 78
frontend/src/pages/Settings/Tabs/Security.vue

@@ -17,7 +17,7 @@ const QuickConfirm = defineAsyncComponent(
 );
 
 const configStore = useConfigStore();
-const { githubAuthentication, sitename } = storeToRefs(configStore);
+const { sitename } = storeToRefs(configStore);
 const settingsStore = useSettingsStore();
 const userAuthStore = useUserAuthStore();
 const { runJob } = useWebsocketStore();
@@ -42,7 +42,7 @@ const validation = reactive({
 const newPassword = ref();
 const oldPassword = ref();
 
-const { isPasswordLinked, isGithubLinked } = settingsStore;
+const { isPasswordLinked } = settingsStore;
 const { currentUser } = storeToRefs(userAuthStore);
 
 const togglePasswordVisibility = refName => {
@@ -82,16 +82,6 @@ const changePassword = () => {
 		}
 	);
 };
-const unlinkPassword = () => {
-	socket.dispatch("users.unlinkPassword", res => {
-		new Toast(res.message);
-	});
-};
-const unlinkGitHub = () => {
-	socket.dispatch("users.unlinkGitHub", res => {
-		new Toast(res.message);
-	});
-};
 const removeSessions = async () => {
 	await runJob("data.users.logoutAll");
 
@@ -199,72 +189,6 @@ watch(validation, newValidation => {
 			<div class="section-margin-bottom" />
 		</div>
 
-		<div v-if="!isPasswordLinked">
-			<h4 class="section-title">Add a password</h4>
-			<p class="section-description">
-				Add a password, as an alternative to signing in with GitHub
-			</p>
-
-			<hr class="section-horizontal-rule" />
-
-			<router-link to="/set_password" class="button is-default"
-				><i class="material-icons icon-with-button">create</i>Set
-				Password
-			</router-link>
-
-			<div class="section-margin-bottom" />
-		</div>
-
-		<div v-if="!isGithubLinked && githubAuthentication">
-			<h4 class="section-title">Link your GitHub account</h4>
-			<p class="section-description">
-				Link your {{ sitename }} account with GitHub
-			</p>
-
-			<hr class="section-horizontal-rule" />
-
-			<a
-				class="button is-github"
-				:href="`${configStore.urls.api}/auth/github/link`"
-			>
-				<div class="icon">
-					<img class="invert" src="/assets/social/github.svg" />
-				</div>
-				&nbsp; Link GitHub to account
-			</a>
-
-			<div class="section-margin-bottom" />
-		</div>
-
-		<div v-if="isPasswordLinked && isGithubLinked">
-			<h4 class="section-title">Remove login methods</h4>
-			<p class="section-description">
-				Remove your password as a login method or unlink GitHub
-			</p>
-
-			<hr class="section-horizontal-rule" />
-
-			<div class="row">
-				<quick-confirm
-					v-if="isPasswordLinked && githubAuthentication"
-					@confirm="unlinkPassword()"
-				>
-					<a class="button is-danger">
-						<i class="material-icons icon-with-button">close</i>
-						Remove password
-					</a>
-				</quick-confirm>
-				<quick-confirm v-if="isGithubLinked" @confirm="unlinkGitHub()">
-					<a class="button is-danger">
-						<i class="material-icons icon-with-button">link_off</i>
-						Remove GitHub from account
-					</a>
-				</quick-confirm>
-			</div>
-
-			<div class="section-margin-bottom" />
-		</div>
-
 		<div>
 			<h4 class="section-title">Log out everywhere</h4>
 			<p class="section-description">

+ 6 - 7
frontend/src/pages/Terms.vue

@@ -75,13 +75,12 @@ const MainFooter = defineAsyncComponent(
 			</p>
 			<p>
 				We may also allow you to use a third party API to sign up for
-				our Site, like GitHub Authentication. Whenever you use this
-				feature, certain information will be transferred from the third
-				party account and will populate your profile here at Musare. It
-				is important to read and understand that third parties privacy
-				and information sharing practices and principles. More
-				importantly, you will be making certain information publicly
-				viewable.
+				our Site. Whenever you use this feature, certain information will
+				be transferred from the third party account and will populate your
+				profile here at Musare. It is important to read and understand that
+				third parties privacy and information sharing practices and
+				principles. More importantly, you will be making certain information
+				publicly viewable.
 			</p>
 			<p>
 				If you register for any feature that requires a password and/or

+ 0 - 10
frontend/src/stores/config.ts

@@ -4,11 +4,6 @@ export const useConfigStore = defineStore("config", {
 	state: (): {
 		cookie: string;
 		sitename: string;
-		recaptcha: {
-			enabled: boolean;
-			key: string;
-		};
-		githubAuthentication: boolean;
 		messages: Record<string, string>;
 		christmas: boolean;
 		footerLinks: Record<string, string | boolean>;
@@ -28,11 +23,6 @@ export const useConfigStore = defineStore("config", {
 	} => ({
 		cookie: "musareSID",
 		sitename: MUSARE_SITENAME,
-		recaptcha: {
-			enabled: false,
-			key: ""
-		},
-		githubAuthentication: false,
 		messages: {
 			accountRemoval:
 				"Your account will be deactivated instantly and your data will shortly be deleted by an admin."

+ 0 - 5
frontend/src/stores/modals.ts

@@ -35,11 +35,6 @@ export const useModalsStore = defineStore("modals", {
 		closeModal(uuid: string, force = false) {
 			Object.entries(this.modals).forEach(([_uuid, modal]) => {
 				if (uuid === _uuid) {
-					if (modal.modal === "register") {
-						const configStore = useConfigStore();
-						if (configStore.recaptcha.enabled)
-							window.location.reload();
-					}
 					const close = () => {
 						const { socket } = useWebsocketsStore();
 						socket.destroyModalListeners(uuid);

+ 0 - 1
frontend/src/stores/settings.ts

@@ -30,7 +30,6 @@ export const useSettingsStore = defineStore("settings", {
 		}
 	},
 	getters: {
-		isGithubLinked: state => state.originalUser.github,
 		isPasswordLinked: state => state.originalUser.password
 	}
 });

+ 2 - 4
frontend/src/stores/userAuth.ts

@@ -40,9 +40,8 @@ export const useUserAuthStore = defineStore("userAuth", () => {
 		username: string;
 		email: string;
 		password: string;
-		recaptchaToken: string;
 	}) => {
-		const { username, email, password, recaptchaToken } = user;
+		const { username, email, password } = user;
 
 		if (!email || !username || !password)
 			throw new Error("Please fill in all fields");
@@ -80,8 +79,7 @@ export const useUserAuthStore = defineStore("userAuth", () => {
 		const data = await websocketStore.runJob("users.register", {
 			username,
 			email,
-			password,
-			recaptchaToken
+			password
 		});
 
 		if (!data?.SID) throw new Error("You must login");

+ 0 - 1
frontend/src/types/global.d.ts

@@ -5,7 +5,6 @@ declare global {
 	var stationInterval: number;
 	var YT: any;
 	var stationNextSongTimeout: any;
-	var grecaptcha: any;
 	var addToPlaylistDropdown: any;
 	var scrollDebounceId: any;
 	var focusedElementBefore: any;