mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-09 07:26:01 -04:00
(user)(auth) don't use mastodon id as a placeholder email; alert if placeholder used as an email
This commit is contained in:
parent
a346a82a32
commit
76ce55f1ed
@ -48,7 +48,7 @@
|
||||
<template #general>
|
||||
<div class="card mb-3">
|
||||
<div class="card-body d-flex flex-column flex-md-row">
|
||||
<div class="mx-2 text-center">
|
||||
<div class="mx-2 text-center" style="min-width: 200px">
|
||||
<p v-if="$isGranted('panel') || $isGranted('users') || $isGranted('community')">
|
||||
<nuxt-link to="/admin" class="badge bg-primary text-white">
|
||||
<Icon v="collective-logo.svg" class="inverted" />
|
||||
@ -126,6 +126,8 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<Alert v-if="$user() && $user()!.email.endsWith('.oauth')" type="warning" message="user.emailMissing" />
|
||||
|
||||
<form :inert="savingEmail" @submit.prevent="changeEmail">
|
||||
<h3 class="h6">
|
||||
<T>user.account.changeEmail.header</T>
|
||||
|
@ -685,6 +685,10 @@ user:
|
||||
Under one account you can have one card per language, and those cards are linked through the common @username.
|
||||
But you can might also want to set up multiple independent accounts, for example one for a work email footer,
|
||||
and a separate one for close friends. If you add them here, you'll be able to quickly switch between those accounts.
|
||||
emailMissing: >
|
||||
Your account was created with a method that didn't share a verified email address with us.
|
||||
Please change the placeholder below to your email and confirm it with a code –
|
||||
this way you'll have a fallback login method in case you lose access to the one you used.
|
||||
|
||||
profile:
|
||||
description: 'Description'
|
||||
|
@ -888,6 +888,10 @@ user:
|
||||
Under one account you can have one card per language, and those cards are linked through the common @username.
|
||||
But you can might also want to set up multiple independent accounts, for example one for a work email footer,
|
||||
and a separate one for close friends. If you add them here, you'll be able to quickly switch between those accounts.
|
||||
emailMissing: >
|
||||
Your account was created with a method that didn't share a verified email address with us.
|
||||
Please change the placeholder below to your email and confirm it with a code –
|
||||
this way you'll have a fallback login method in case you lose access to the one you used.
|
||||
|
||||
profile:
|
||||
description: 'Description'
|
||||
|
@ -1532,6 +1532,10 @@ user:
|
||||
W ramach jednego konta możesz stworzyć po jednej wizytówce na język, będą one wtedy ze sobą związane poprzez wspólną @nazwę_użytkownicza.
|
||||
Ale możesz też chcieć założyć niezależne konta, na przykład jedno do stopki służbowego maila,
|
||||
a drugie dla bliskich znajomych. Jeśli dodasz je tutaj, będzie można szybko się między tymi kontami przełączać.
|
||||
emailMissing: >
|
||||
Twoje konto zostało utworzone z użyciem metody logowania, która nie udostępniła nam zweryfikowanego adresu email.
|
||||
Aby mieć dostępny zapasowy sposób logowania, gdybyś straciłx dostęp do obecnego,
|
||||
wpisz swój adres email poniżej i potwierdź go kodem.
|
||||
|
||||
profile:
|
||||
description: 'Opis'
|
||||
|
75
server/__tmp_fix_mastodon_emails.ts
Normal file
75
server/__tmp_fix_mastodon_emails.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import './setup.ts';
|
||||
|
||||
import readline from 'readline';
|
||||
|
||||
import dbConnection from './db.ts';
|
||||
|
||||
import { normaliseExternalId } from '~/server/express/user.ts';
|
||||
|
||||
// TODO remove export after deployment migration
|
||||
|
||||
const fix = async (): Promise<void> => {
|
||||
const db = await dbConnection();
|
||||
|
||||
const data = (await db.all<{ id: string; email: string; type: string; payload: string }>(`
|
||||
SELECT u.id, u.email, a.type, a.payload
|
||||
FROM users u
|
||||
LEFT JOIN authenticators a on a.userId = u.id
|
||||
WHERE a.type in ('mastodon', 'indieauth')
|
||||
`));
|
||||
|
||||
const changes = {} as Record<string, string>;
|
||||
// @ts-ignore
|
||||
for (const { id, email, type, payload } of data) {
|
||||
let payloadId;
|
||||
try {
|
||||
payloadId = JSON.parse(payload).id;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type === 'mastodon') {
|
||||
if (email === payloadId) {
|
||||
changes[id] = `${normaliseExternalId(payloadId)}@mastodon.oauth`;
|
||||
console.log(id, email, '->', changes[id]);
|
||||
} else {
|
||||
console.log(id, email, '(unchanged)');
|
||||
}
|
||||
} else if (type === 'indieauth') {
|
||||
if (email === `indieauth@${normaliseExternalId(payloadId)}`) {
|
||||
changes[id] = `${normaliseExternalId(payloadId)}@indieauth.oauth`;
|
||||
console.log(id, email, '->', changes[id]);
|
||||
} else {
|
||||
console.log(id, email, '(unchanged)');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(changes);
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
rl.question('Do you want to persist the changes? (y/n): ', (answer) => {
|
||||
if (answer.toLowerCase() === 'y') {
|
||||
console.log('Proceeding...');
|
||||
|
||||
for (const [id, email] of Object.entries(changes)) {
|
||||
db.get(`
|
||||
UPDATE users
|
||||
SET email='${email}'
|
||||
WHERE id='${id}'
|
||||
`);
|
||||
}
|
||||
} else {
|
||||
console.log('Operation cancelled.');
|
||||
process.exit(0);
|
||||
}
|
||||
rl.close();
|
||||
});
|
||||
};
|
||||
|
||||
fix();
|
@ -704,6 +704,10 @@ router.get('/user/social-redirect/:provider/:locale', handleErrorAsync(async (re
|
||||
return res.redirect(`/api/connect/${req.params.provider}?${new URLSearchParams(searchParams)}`);
|
||||
}));
|
||||
|
||||
// TODO remove export after deployment migration
|
||||
export const normaliseExternalId = (id: string): string => id.replace(/@/g, '_').replace(/^https?:\/\//, '')
|
||||
.replace(new RegExp('/', 'g'), '_');
|
||||
|
||||
// happens on home
|
||||
router.get('/user/social/:provider', handleErrorAsync(async (req, res) => {
|
||||
if (!req.session.grant || !req.session.grant.response ||
|
||||
@ -735,7 +739,7 @@ router.get('/user/social/:provider', handleErrorAsync(async (req, res) => {
|
||||
: req.user;
|
||||
|
||||
const dbUser = await fetchOrCreateUser(req.db, user || {
|
||||
email: payload.email || `${payload.id}@${req.params.provider}.oauth`,
|
||||
email: payload.email || `${normaliseExternalId(payload.id)}@${req.params.provider}.oauth`,
|
||||
name: payload.name,
|
||||
}, req.params.provider);
|
||||
|
||||
|
@ -108,7 +108,7 @@ if (enableApple) {
|
||||
|
||||
interface SocialProfile {
|
||||
id: string;
|
||||
email: string;
|
||||
email: string | null;
|
||||
name: string;
|
||||
username?: string;
|
||||
avatar?: string;
|
||||
@ -168,8 +168,7 @@ export const handlers: Record<string, (r: GrantResponse) => SocialProfile> = {
|
||||
const acct = `${r.profile.username}@${instance}`;
|
||||
return {
|
||||
id: acct,
|
||||
// very possibly not really operated by the user
|
||||
email: acct,
|
||||
email: null,
|
||||
name: acct,
|
||||
avatar: r.profile.avatar,
|
||||
access_token: r.access_token,
|
||||
@ -179,7 +178,7 @@ export const handlers: Record<string, (r: GrantResponse) => SocialProfile> = {
|
||||
indieauth(r: GrantResponse): SocialProfile {
|
||||
return {
|
||||
id: r.profile.me,
|
||||
email: `indieauth@${r.profile.domain}`,
|
||||
email: null,
|
||||
name: r.profile.domain,
|
||||
instance: (r as { instance: string }).instance,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user