mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-28 07:20:49 -04:00
Merge branch 'indieauth'
This commit is contained in:
commit
cd50208c37
@ -1,16 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center">
|
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center">
|
||||||
<span class="my-2">
|
<span class="my-2">
|
||||||
<Icon :v="providerOptions.icon || provider" set="b"/>
|
<Icon :v="providerOptions.icon || provider" set="b"
|
||||||
|
:class="[providerOptions.icon && providerOptions.icon.endsWith('.png') ? 'mx-1 invertible' : '']"/>
|
||||||
{{ providerOptions.name }}
|
{{ providerOptions.name }}
|
||||||
|
<button v-if="providerOptions.deprecated" class="badge bg-light text-dark border border-warning" @click="depreciationNotice(providerOptions.deprecated)">
|
||||||
|
<Icon v="exclamation-triangle"/>
|
||||||
|
<T>user.login.deprecated</T>
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="connection === undefined">
|
<span v-if="connection === undefined">
|
||||||
<template v-if="providerOptions.instanceRequired">
|
<template v-if="providerOptions.instanceRequired">
|
||||||
<form v-if="formShown"
|
<form v-if="formShown"
|
||||||
:action="`${homeUrl}/api/user/social-redirect/${provider}/${config.locale}`"
|
:action="providerOptions.redirectViaHome ? `${homeUrl}/api/user/social-redirect/${provider}/${config.locale}` : `/api/connect/${provider}`"
|
||||||
class="input-group input-group-sm">
|
class="input-group input-group-sm">
|
||||||
<input type="text" name="instance" class="form-control" autofocus required
|
<input type="text" name="instance" class="form-control" autofocus required
|
||||||
:placeholder="$t('user.login.instancePlaceholder')"/>
|
:placeholder="$t(providerOptions.domain ? 'user.login.domainPlaceholder' : 'user.login.instancePlaceholder')"/>
|
||||||
<button type="submit" class="btn btn-outline-secondary">
|
<button type="submit" class="btn btn-outline-secondary">
|
||||||
<Icon v="link"/>
|
<Icon v="link"/>
|
||||||
</button>
|
</button>
|
||||||
@ -20,21 +25,21 @@
|
|||||||
<T>user.socialConnection.connect</T>
|
<T>user.socialConnection.connect</T>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<a v-else :href="`${homeUrl}/api/user/social-redirect/${provider}/${config.locale}`" class="badge bg-light text-dark border">
|
<a v-else :href="providerOptions.redirectViaHome ? `${homeUrl}/api/user/social-redirect/${provider}/${config.locale}` : `/api/connect/${provider}`" class="badge bg-light text-dark border">
|
||||||
<Icon v="link"/>
|
<Icon v="link"/>
|
||||||
<T>user.socialConnection.connect</T>
|
<T>user.socialConnection.connect</T>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="text-center">
|
<span v-else class="text-center">
|
||||||
<span class="mr-3">
|
<span class="me-2">
|
||||||
<a href="#" @click.prevent="$emit('setAvatar', provider)">
|
<a v-if="providerOptions.avatars && connection.avatar" href="#" @click.prevent="$emit('setAvatar', provider)">
|
||||||
<Avatar :src="connection.avatar" :user="$user()" dsize="2rem"/>
|
<Avatar :src="connection.avatar" :user="$user()" dsize="2rem"/>
|
||||||
</a>
|
</a>
|
||||||
{{connection.name}}
|
{{connection.name}}
|
||||||
</span>
|
</span>
|
||||||
<br class="d-md-none"/>
|
<br class="d-md-none"/>
|
||||||
<a :href="`${homeUrl}/api/user/social-redirect/${provider}/${config.locale}` + (providerOptions.instanceRequired ? '?instance=' + connection.name.split('@')[1] : '')"
|
<a :href="(providerOptions.redirectViaHome ? `${homeUrl}/api/user/social-redirect/${provider}/${config.locale}` : `/api/connect/${provider}`) + (providerOptions.instanceRequired ? '?instance=' + connection.name.split('@')[1] : '')"
|
||||||
class="badge bg-light text-dark border">
|
class="badge bg-light text-dark border">
|
||||||
<Icon v="sync"/>
|
<Icon v="sync"/>
|
||||||
<T>user.socialConnection.refresh</T>
|
<T>user.socialConnection.refresh</T>
|
||||||
</a>
|
</a>
|
||||||
@ -48,31 +53,34 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
provider: { required: true },
|
provider: { required: true },
|
||||||
providerOptions: { required: true },
|
providerOptions: { required: true },
|
||||||
connection: {},
|
connection: {},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
disconnecting: false,
|
disconnecting: false,
|
||||||
homeUrl: process.env.HOME_URL,
|
homeUrl: process.env.HOME_URL,
|
||||||
formShown: false,
|
formShown: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async disconnect() {
|
||||||
|
await this.$confirm(this.$t('user.socialConnection.disconnectConfirm', {email: this.$user().email}), 'danger');
|
||||||
|
|
||||||
|
this.disconnecting = true;
|
||||||
|
try {
|
||||||
|
const response = await this.$post(`/user/social-connection/${this.provider}/disconnect`);
|
||||||
|
this.$emit('disconnected', response);
|
||||||
|
} finally {
|
||||||
|
this.disconnecting = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
async depreciationNotice(link) {
|
||||||
async disconnect() {
|
await this.$alert(this.$t('user.login.depreciationNotice', {link}), 'warning');
|
||||||
await this.$confirm(this.$t('user.socialConnection.disconnectConfirm', {email: this.$user().email}), 'danger');
|
}
|
||||||
|
},
|
||||||
this.disconnecting = true;
|
}
|
||||||
try {
|
|
||||||
const response = await this.$post(`/user/social-connection/${this.provider}/disconnect`);
|
|
||||||
this.$emit('disconnected', response);
|
|
||||||
} finally {
|
|
||||||
this.disconnecting = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
<Icon :v="options.icon || provider" set="b"/>
|
<Icon :v="options.icon || provider" set="b"/>
|
||||||
{{ options.name }}
|
{{ options.name }}
|
||||||
|
|
||||||
<form :action="`${homeUrl}/api/user/social-redirect/${provider}/${config.locale}`"
|
<form :action="link"
|
||||||
v-if="options.instanceRequired" class="input-group my-2">
|
v-if="options.instanceRequired" class="input-group my-2">
|
||||||
<input type="text" name="instance" class="form-control" autofocus required ref="instance"
|
<input type="text" name="instance" class="form-control" autofocus required ref="instance"
|
||||||
:placeholder="$t('user.login.instancePlaceholder')">
|
:placeholder="$t(options.domain ? 'user.login.domainPlaceholder' : 'user.login.instancePlaceholder')"/>
|
||||||
<button type="submit" class="btn btn-outline-primary">
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
<Icon v="arrow-right"/>
|
<Icon v="arrow-right"/>
|
||||||
</button>
|
</button>
|
||||||
@ -15,11 +15,20 @@
|
|||||||
<button v-else-if="options.instanceRequired && !formShown"
|
<button v-else-if="options.instanceRequired && !formShown"
|
||||||
class="btn btn-outline-primary"
|
class="btn btn-outline-primary"
|
||||||
@click="showForm">
|
@click="showForm">
|
||||||
<Icon :v="options.icon || provider" set="b"/>
|
<Icon :v="options.icon || provider" set="b"
|
||||||
|
:class="[options.icon && options.icon.endsWith('.png') ? 'mx-1 invertible' : '']"/>
|
||||||
{{ options.name }}
|
{{ options.name }}
|
||||||
</button>
|
</button>
|
||||||
<a v-else :href="`${homeUrl}/api/user/social-redirect/${provider}/${config.locale}`"
|
<a v-else-if="options.deprecated" :href="link"
|
||||||
class="btn btn-outline-primary">
|
class="btn btn-outline-secondary btn-sm"
|
||||||
|
@click.prevent="depreciationNotice(options.deprecated)"
|
||||||
|
>
|
||||||
|
<Icon :v="options.icon || provider" set="b"/>
|
||||||
|
{{ options.name }}
|
||||||
|
</a>
|
||||||
|
<a v-else :href="link"
|
||||||
|
class="btn btn-outline-primary"
|
||||||
|
>
|
||||||
<Icon :v="options.icon || provider" set="b"/>
|
<Icon :v="options.icon || provider" set="b"/>
|
||||||
{{ options.name }}
|
{{ options.name }}
|
||||||
</a>
|
</a>
|
||||||
@ -37,11 +46,20 @@ export default {
|
|||||||
formShown: false,
|
formShown: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
link() {
|
||||||
|
return this.options.redirectViaHome ? `${this.homeUrl}/api/user/social-redirect/${this.provider}/${this.config.locale}` : `/api/connect/${this.provider}`
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showForm() {
|
showForm() {
|
||||||
this.formShown = true;
|
this.formShown = true;
|
||||||
this.$nextTick(() => this.$refs.instance.focus());
|
this.$nextTick(() => this.$refs.instance.focus());
|
||||||
}
|
},
|
||||||
|
async depreciationNotice(link) {
|
||||||
|
await this.$confirm(this.$t('user.login.depreciationNotice', {link}), 'warning');
|
||||||
|
window.location.href = this.link;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -497,6 +497,12 @@ user:
|
|||||||
Registering lets you manage your cards ({/@example=like this one}).
|
Registering lets you manage your cards ({/@example=like this one}).
|
||||||
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instance'
|
instancePlaceholder: 'Instance'
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validate'
|
action: 'Validate'
|
||||||
invalid: 'Invalid code.'
|
invalid: 'Invalid code.'
|
||||||
|
@ -421,6 +421,13 @@ user:
|
|||||||
Mit der Registrierung kannst du deine Visitenkarten verwalten ({/@example=wie diese}).
|
Mit der Registrierung kannst du deine Visitenkarten verwalten ({/@example=wie diese}).
|
||||||
passwordless: 'Die Website speichert keine Passwörter. {https://avris.it/blog/passwords-are-passé=Weitere Infos.}'
|
passwordless: 'Die Website speichert keine Passwörter. {https://avris.it/blog/passwords-are-passé=Weitere Infos.}'
|
||||||
instancePlaceholder: 'Instanz'
|
instancePlaceholder: 'Instanz'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validieren'
|
action: 'Validieren'
|
||||||
invalid: 'Ungültiger Code.'
|
invalid: 'Ungültiger Code.'
|
||||||
|
23
locale/en/blog/facebook-login-deprecated.md
Normal file
23
locale/en/blog/facebook-login-deprecated.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# We don't recommend using Facebook login
|
||||||
|
|
||||||
|
<small>2022-04-23 | [@andrea](/@andrea)</small>
|
||||||
|
|
||||||
|
We all know that Meta/Facebook is a company that couldn't give a shit about morality or users' privacy.
|
||||||
|
But did you know they're also unfriendly towards developers and try to impose their prudish, conservative views on independent websites?
|
||||||
|
|
||||||
|
This morning they've disabled two apps of mine whose whole purpose was simply to let people log in to a website using their Facebook account.
|
||||||
|
Nothing more, no actual dependency on Facebook, just the “log in with” button.
|
||||||
|
|
||||||
|
Why? One of them, [NakedAdventure](https://naked-adventure.eu/), is a map of nude beaches and contains small amounts of non-sexual nudity.
|
||||||
|
The other, [OurSong](https://oursong.eurovote.eu/), is a harmless game where people vote for their favourite songs
|
||||||
|
– but it's only accessible for members, so Facebook didn't like the fact that they cannot sniff around.
|
||||||
|
They have blocked the apps without notice, making independent websites inaccessible for some users on a whim.
|
||||||
|
|
||||||
|
If they think it's okay to suddenly cut people off other websites just because there was some non-sexual nudity present
|
||||||
|
or because they weren't able to snoop around, who knows if one day they won't block Pronouns.page because of the queer content?
|
||||||
|
After all, in countries like Russia distributing information about LGBTQ+ issues is already considered adult content.
|
||||||
|
|
||||||
|
Users of Pronouns.page seem to dislike Facebook anyway – only 2.76% of you has login with Facebook set up
|
||||||
|
(compared for example to 38,95% of people using login with Twitter).
|
||||||
|
But to those who use it as their primary login option –
|
||||||
|
**we strongly recommend setting up a different login method and ditching Facebook**.
|
@ -521,6 +521,12 @@ user:
|
|||||||
Registering lets you manage your cards ({/@example=like this one}).
|
Registering lets you manage your cards ({/@example=like this one}).
|
||||||
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instance'
|
instancePlaceholder: 'Instance'
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validate'
|
action: 'Validate'
|
||||||
invalid: 'Invalid code.'
|
invalid: 'Invalid code.'
|
||||||
|
@ -482,6 +482,13 @@ user:
|
|||||||
Registering lets you manage your cards ({/@example=like this one}).
|
Registering lets you manage your cards ({/@example=like this one}).
|
||||||
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instance'
|
instancePlaceholder: 'Instance'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validate'
|
action: 'Validate'
|
||||||
invalid: 'Nevalida kodo.'
|
invalid: 'Nevalida kodo.'
|
||||||
|
@ -506,6 +506,13 @@ user:
|
|||||||
Registrarte te permite manejar tus tarjetas ({/@example=como esta}).
|
Registrarte te permite manejar tus tarjetas ({/@example=como esta}).
|
||||||
passwordless: 'Este sitio web no guarda las contraseñas. {https://avris.it/blog/passwords-are-passé=Más información.}'
|
passwordless: 'Este sitio web no guarda las contraseñas. {https://avris.it/blog/passwords-are-passé=Más información.}'
|
||||||
instancePlaceholder: 'Instancia'
|
instancePlaceholder: 'Instancia'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validar'
|
action: 'Validar'
|
||||||
invalid: 'Código inválido.'
|
invalid: 'Código inválido.'
|
||||||
|
@ -424,6 +424,13 @@ user:
|
|||||||
S’inscrire vous permet de gérer vos cartes ({/@example=comme celle-ci}).
|
S’inscrire vous permet de gérer vos cartes ({/@example=comme celle-ci}).
|
||||||
passwordless: 'Ce site ne stocke aucun mot de passe. {https://avris.it/blog/passwords-are-passé=Plus d’infos.}'
|
passwordless: 'Ce site ne stocke aucun mot de passe. {https://avris.it/blog/passwords-are-passé=Plus d’infos.}'
|
||||||
instancePlaceholder: 'Instance'
|
instancePlaceholder: 'Instance'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Valider'
|
action: 'Valider'
|
||||||
invalid: 'Code invalide.'
|
invalid: 'Code invalide.'
|
||||||
|
@ -405,6 +405,13 @@ user:
|
|||||||
Registrar-se te permite dirigir os cartões ({/@example=como esta}).
|
Registrar-se te permite dirigir os cartões ({/@example=como esta}).
|
||||||
passwordless: 'O site não grava qualquer senha. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'O site não grava qualquer senha. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instance' # TODO
|
instancePlaceholder: 'Instance' # TODO
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validar'
|
action: 'Validar'
|
||||||
invalid: 'Código inválido.'
|
invalid: 'Código inválido.'
|
||||||
|
@ -498,6 +498,13 @@ user:
|
|||||||
Registering lets you manage your cards ({/@example=like this one}).
|
Registering lets you manage your cards ({/@example=like this one}).
|
||||||
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instance'
|
instancePlaceholder: 'Instance'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validate'
|
action: 'Validate'
|
||||||
invalid: 'Invalid code.'
|
invalid: 'Invalid code.'
|
||||||
|
@ -426,6 +426,13 @@ user:
|
|||||||
ご登録いただいた方は、カードの設定を行うことができます。({/@example=カードの例}).
|
ご登録いただいた方は、カードの設定を行うことができます。({/@example=カードの例}).
|
||||||
passwordless: 'このウェブサイトはパスワードを保存しません。 {https://avris.it/blog/passwords-are-passé=詳細はこちら。}'
|
passwordless: 'このウェブサイトはパスワードを保存しません。 {https://avris.it/blog/passwords-are-passé=詳細はこちら。}'
|
||||||
instancePlaceholder: 'サーバー'
|
instancePlaceholder: 'サーバー'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: '確認'
|
action: '確認'
|
||||||
invalid: '無効なコード'
|
invalid: '無効なコード'
|
||||||
|
@ -495,6 +495,13 @@ user:
|
|||||||
등록하면 카드를 ({/@example=이렇게}) 관리할 수 있습니다.
|
등록하면 카드를 ({/@example=이렇게}) 관리할 수 있습니다.
|
||||||
passwordless: '웹사이트는 비밀번호를 저장하지 않습니다. {https://avris.it/blog/passwords-are-passé=추가 정보.}'
|
passwordless: '웹사이트는 비밀번호를 저장하지 않습니다. {https://avris.it/blog/passwords-are-passé=추가 정보.}'
|
||||||
instancePlaceholder: '사례'
|
instancePlaceholder: '사례'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: '확인'
|
action: '확인'
|
||||||
invalid: '유효하지 않은 코드'
|
invalid: '유효하지 않은 코드'
|
||||||
|
@ -402,6 +402,13 @@ user:
|
|||||||
Rejistrarte te permete kontentarte tus kartas ({/@example=komo esta}).
|
Rejistrarte te permete kontentarte tus kartas ({/@example=komo esta}).
|
||||||
passwordless: 'Este sitio gueb no guadra las kontrasenyas. {https://avris.it/blog/passwords-are-passé=Mas informasion.}'
|
passwordless: 'Este sitio gueb no guadra las kontrasenyas. {https://avris.it/blog/passwords-are-passé=Mas informasion.}'
|
||||||
instancePlaceholder: 'Instansia'
|
instancePlaceholder: 'Instansia'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Balidar'
|
action: 'Balidar'
|
||||||
invalid: 'Kodiche enfirmo.'
|
invalid: 'Kodiche enfirmo.'
|
||||||
|
@ -424,6 +424,13 @@ user:
|
|||||||
Door te registreren kun je een kaart ({/@example=zoals deze}) maken.
|
Door te registreren kun je een kaart ({/@example=zoals deze}) maken.
|
||||||
passwordless: 'De website slaat geen wachtwoorden op. {https://avris.it/blog/passwords-are-passé=Meer info.}'
|
passwordless: 'De website slaat geen wachtwoorden op. {https://avris.it/blog/passwords-are-passé=Meer info.}'
|
||||||
instancePlaceholder: 'Instantie'
|
instancePlaceholder: 'Instantie'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Valideer'
|
action: 'Valideer'
|
||||||
invalid: 'Ongeldige code.'
|
invalid: 'Ongeldige code.'
|
||||||
|
@ -401,6 +401,13 @@ user:
|
|||||||
Å registrere seg lar deg redigere kortene dine ({/@example=sånn som denne}).
|
Å registrere seg lar deg redigere kortene dine ({/@example=sånn som denne}).
|
||||||
passwordless: 'Denne nettsiden lagrer ingen passord. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'Denne nettsiden lagrer ingen passord. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Forekomst'
|
instancePlaceholder: 'Forekomst'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Gyldig'
|
action: 'Gyldig'
|
||||||
invalid: 'Ugyldig kode.'
|
invalid: 'Ugyldig kode.'
|
||||||
|
@ -1196,6 +1196,12 @@ user:
|
|||||||
Założenie konta pozwala na zarządzanie swoimi wizytówkami ({/@example=takimi jak ta}).
|
Założenie konta pozwala na zarządzanie swoimi wizytówkami ({/@example=takimi jak ta}).
|
||||||
passwordless: 'Strona nie zapisuje żadnych haseł. {https://avris.it/blog/passwords-are-passé=Więcej info.}'
|
passwordless: 'Strona nie zapisuje żadnych haseł. {https://avris.it/blog/passwords-are-passé=Więcej info.}'
|
||||||
instancePlaceholder: 'Instancja'
|
instancePlaceholder: 'Instancja'
|
||||||
|
domainPlaceholder: 'Domena'
|
||||||
|
deprecated: 'Odradzane'
|
||||||
|
depreciationNotice: >
|
||||||
|
Ten dostawca uwierzytelniania nie jest godny zaufania.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Więcej szczegółów pod tym linkiem</a>.
|
||||||
|
Mocno polecamy włączenie innej metody uwierzytelniania.
|
||||||
code:
|
code:
|
||||||
action: 'Sprawdź'
|
action: 'Sprawdź'
|
||||||
invalid: 'Kod nieprawidłowy.'
|
invalid: 'Kod nieprawidłowy.'
|
||||||
|
@ -427,6 +427,13 @@ user:
|
|||||||
Registrar-se te permite dirigir os cartões ({/@example=como esta}).
|
Registrar-se te permite dirigir os cartões ({/@example=como esta}).
|
||||||
passwordless: 'O site não grava qualquer senha. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'O site não grava qualquer senha. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instância'
|
instancePlaceholder: 'Instância'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validar'
|
action: 'Validar'
|
||||||
invalid: 'Código inválido.'
|
invalid: 'Código inválido.'
|
||||||
|
@ -518,6 +518,13 @@ user:
|
|||||||
Регистрация позволяет вам управлять своими аккаунтами/карточками ({/@exemple=как, например, этой}).
|
Регистрация позволяет вам управлять своими аккаунтами/карточками ({/@exemple=как, например, этой}).
|
||||||
passwordless: 'Сайт не хранит пароли. {https://avris.it/blog/passwords-are-passé=Больше информации}'
|
passwordless: 'Сайт не хранит пароли. {https://avris.it/blog/passwords-are-passé=Больше информации}'
|
||||||
instancePlaceholder: 'инстанция'
|
instancePlaceholder: 'инстанция'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Подтвердить'
|
action: 'Подтвердить'
|
||||||
invalid: 'Неверный код.'
|
invalid: 'Неверный код.'
|
||||||
|
@ -476,6 +476,13 @@ user:
|
|||||||
Registering låter dig hantera dina kort ({/@andrea=som det här}).
|
Registering låter dig hantera dina kort ({/@andrea=som det här}).
|
||||||
passwordless: 'Webbplatsen lagrar inga lösenord. {https://avris.it/blog/passwords-are-passé=Mer information.}'
|
passwordless: 'Webbplatsen lagrar inga lösenord. {https://avris.it/blog/passwords-are-passé=Mer information.}'
|
||||||
instancePlaceholder: 'Instans'
|
instancePlaceholder: 'Instans'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Bekräfta'
|
action: 'Bekräfta'
|
||||||
invalid: 'Ogiltig kod.'
|
invalid: 'Ogiltig kod.'
|
||||||
|
@ -541,6 +541,13 @@ user:
|
|||||||
Реєстрація дозволяє вам управляти своїми акаунтами/картками ({/@exemple=як, наприклад, цією}).
|
Реєстрація дозволяє вам управляти своїми акаунтами/картками ({/@exemple=як, наприклад, цією}).
|
||||||
passwordless: 'Сайт не зберігає паролі. {https://avris.it/blog/passwords-are-passé=Більше інформації}'
|
passwordless: 'Сайт не зберігає паролі. {https://avris.it/blog/passwords-are-passé=Більше інформації}'
|
||||||
instancePlaceholder: 'інстанція'
|
instancePlaceholder: 'інстанція'
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Підтвердити'
|
action: 'Підтвердити'
|
||||||
invalid: 'Невірний код.'
|
invalid: 'Невірний код.'
|
||||||
|
@ -395,6 +395,13 @@ user:
|
|||||||
Registering lets you manage your cards ({/@example=like this one}).
|
Registering lets you manage your cards ({/@example=like this one}).
|
||||||
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
passwordless: 'The website doesn''t store any passwords. {https://avris.it/blog/passwords-are-passé=More info.}'
|
||||||
instancePlaceholder: 'Instance' # TODO
|
instancePlaceholder: 'Instance' # TODO
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: 'Validate'
|
action: 'Validate'
|
||||||
invalid: 'Invalid code.'
|
invalid: 'Invalid code.'
|
||||||
|
@ -380,6 +380,13 @@ user:
|
|||||||
註冊可以讓你管理你的卡({/@example=像這個})。
|
註冊可以讓你管理你的卡({/@example=像這個})。
|
||||||
passwordless: '該網站不存儲任何密碼。 {https://avris.it/blog/passwords-are-passé=更多信息。}'
|
passwordless: '該網站不存儲任何密碼。 {https://avris.it/blog/passwords-are-passé=更多信息。}'
|
||||||
instancePlaceholder: 'Instance' # TODO
|
instancePlaceholder: 'Instance' # TODO
|
||||||
|
# TODO
|
||||||
|
domainPlaceholder: 'Domain'
|
||||||
|
deprecated: 'Deprecated'
|
||||||
|
depreciationNotice: >
|
||||||
|
This is not a reliable authentication provider.
|
||||||
|
<a href="%link%" target="_blank" rel="noopener">Check out this link for more details</a>.
|
||||||
|
We highly recommend making sure that you have a different login method available.
|
||||||
code:
|
code:
|
||||||
action: '證實'
|
action: '證實'
|
||||||
invalid: '不對代碼'
|
invalid: '不對代碼'
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
"nuxt": "^2.15.2",
|
"nuxt": "^2.15.2",
|
||||||
"pageres": "^6.2.3",
|
"pageres": "^6.2.3",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.0",
|
||||||
|
"query-string": "^7.1.1",
|
||||||
"rtlcss": "^3.1.2",
|
"rtlcss": "^3.1.2",
|
||||||
"sha1": "^1.1.1",
|
"sha1": "^1.1.1",
|
||||||
"speakeasy": "^2.0.0",
|
"speakeasy": "^2.0.0",
|
||||||
|
@ -6,17 +6,25 @@ import SQL from 'sql-template-strings';
|
|||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { handleErrorAsync } from "../../src/helpers";
|
import { handleErrorAsync } from "../../src/helpers";
|
||||||
|
import queryString from 'query-string';
|
||||||
|
|
||||||
const normalizeDomainName = (domain) => {
|
const normalizeDomainName = (domain) => {
|
||||||
const url = new URL('https://' + domain);
|
const url = new URL('https://' + domain.replace(/^https?:\/\//, ''));
|
||||||
assert(url.port === '');
|
assert(url.port === '');
|
||||||
return url.hostname;
|
return url.hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const baseUrl = process.env.BASE_URL || process.env.HOME_URL || 'https://pronouns.page';
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
mastodon: {
|
mastodon: {
|
||||||
scopes: ['read:accounts'],
|
scopes: ['read:accounts'],
|
||||||
redirect_uri: `${process.env.HOME_URL || 'https://pronouns.page'}/api/user/social/mastodon`,
|
redirect_uri: `${baseUrl}/api/user/social/mastodon`,
|
||||||
|
},
|
||||||
|
indieauth: {
|
||||||
|
server_uri: 'https://indieauth.com/auth',
|
||||||
|
client_id: baseUrl,
|
||||||
|
redirect_uri: `${baseUrl}/api/user/social/indieauth`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,6 +60,7 @@ const mastodonGetOAuthKeys = async (db, instance) => {
|
|||||||
`);
|
`);
|
||||||
return keys;
|
return keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
router.get('/connect/mastodon', handleErrorAsync(async (req, res) => {
|
router.get('/connect/mastodon', handleErrorAsync(async (req, res) => {
|
||||||
assert(req.query.instance);
|
assert(req.query.instance);
|
||||||
const instance = normalizeDomainName(req.query.instance);
|
const instance = normalizeDomainName(req.query.instance);
|
||||||
@ -64,6 +73,7 @@ router.get('/connect/mastodon', handleErrorAsync(async (req, res) => {
|
|||||||
response_type: 'code',
|
response_type: 'code',
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
router.get('/user/social/mastodon', handleErrorAsync(async (req, res, next) => {
|
router.get('/user/social/mastodon', handleErrorAsync(async (req, res, next) => {
|
||||||
if (!req.session.grant || !req.session.grant.instance || !req.query.code) {
|
if (!req.session.grant || !req.session.grant.instance || !req.query.code) {
|
||||||
next();
|
next();
|
||||||
@ -99,7 +109,47 @@ router.get('/user/social/mastodon', handleErrorAsync(async (req, res, next) => {
|
|||||||
response.instance = instance;
|
response.instance = instance;
|
||||||
req.session.grant.response = response;
|
req.session.grant.response = response;
|
||||||
next();
|
next();
|
||||||
return;
|
}));
|
||||||
|
|
||||||
|
router.get('/connect/indieauth', handleErrorAsync(async (req, res) => {
|
||||||
|
assert(req.query.instance);
|
||||||
|
const instance = normalizeDomainName(req.query.instance);
|
||||||
|
req.session.grant = { instance };
|
||||||
|
res.redirect(`${config.indieauth.server_uri}?` + new URLSearchParams({
|
||||||
|
me: `https://${instance}`,
|
||||||
|
client_id: config.indieauth.client_id,
|
||||||
|
redirect_uri: config.indieauth.redirect_uri,
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.get('/user/social/indieauth', handleErrorAsync(async (req, res, next) => {
|
||||||
|
if (!req.session.grant || !req.session.grant.instance || !req.query.code) { next(); return; }
|
||||||
|
|
||||||
|
const response = await fetch(config.indieauth.server_uri, {
|
||||||
|
method: 'POST',
|
||||||
|
body: new URLSearchParams({
|
||||||
|
code: req.query.code,
|
||||||
|
client_id: config.indieauth.client_id,
|
||||||
|
redirect_uri: config.indieauth.redirect_uri,
|
||||||
|
}).toString(),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'User-Agent': 'pronouns.page',
|
||||||
|
},
|
||||||
|
}).then(res => res.text());
|
||||||
|
|
||||||
|
const profile = queryString.parse(response);
|
||||||
|
|
||||||
|
if (!profile || !profile.me) { next(); return; }
|
||||||
|
|
||||||
|
profile.domain = normalizeDomainName(profile.me);
|
||||||
|
|
||||||
|
req.session.grant.response = {
|
||||||
|
profile,
|
||||||
|
instance: req.session.grant.instance,
|
||||||
|
access_token: true,
|
||||||
|
};
|
||||||
|
next();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -32,6 +32,7 @@ module.exports.config = {
|
|||||||
},
|
},
|
||||||
// non-grant, but things break if it's not there
|
// non-grant, but things break if it's not there
|
||||||
mastodon: {},
|
mastodon: {},
|
||||||
|
indieauth: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.handlers = {
|
module.exports.handlers = {
|
||||||
@ -84,6 +85,15 @@ module.exports.handlers = {
|
|||||||
name: acct,
|
name: acct,
|
||||||
avatar: r.profile.avatar,
|
avatar: r.profile.avatar,
|
||||||
access_token: r.access_token,
|
access_token: r.access_token,
|
||||||
|
instance: r.instance,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
indieauth(r) {
|
||||||
|
return {
|
||||||
|
id: r.profile.me,
|
||||||
|
email: 'indieauth@' + r.profile.domain,
|
||||||
|
name: r.profile.domain,
|
||||||
|
instance: r.instance,
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -3,18 +3,36 @@ export const socialProviders = {
|
|||||||
name: 'Mastodon',
|
name: 'Mastodon',
|
||||||
instanceRequired: true,
|
instanceRequired: true,
|
||||||
linkRegex: (p) => `^https?://(?:www.)?${p.name.split('@')[1]}/(?:(?:web/)?@|users/)?${p.name.split('@')[0]}/?$`,
|
linkRegex: (p) => `^https?://(?:www.)?${p.name.split('@')[1]}/(?:(?:web/)?@|users/)?${p.name.split('@')[0]}/?$`,
|
||||||
|
avatars: true,
|
||||||
|
},
|
||||||
|
indieauth: {
|
||||||
|
name: 'IndieAuth',
|
||||||
|
instanceRequired: true,
|
||||||
|
domain: true,
|
||||||
|
icon: 'indieauth.png',
|
||||||
|
iconMargin: true,
|
||||||
|
avatars: false,
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
name: 'Twitter',
|
name: 'Twitter',
|
||||||
linkRegex: (p) => `^https?://(?:www.)?twitter.com/${p.name}/?$`,
|
linkRegex: (p) => `^https?://(?:www.)?twitter.com/${p.name}/?$`,
|
||||||
|
redirectViaHome: true,
|
||||||
|
avatars: true,
|
||||||
},
|
},
|
||||||
discord: {
|
discord: {
|
||||||
name: 'Discord',
|
name: 'Discord',
|
||||||
},
|
redirectViaHome: true,
|
||||||
facebook: {
|
avatars: true,
|
||||||
name: 'Facebook',
|
|
||||||
},
|
},
|
||||||
google: {
|
google: {
|
||||||
name: 'Google',
|
name: 'Google',
|
||||||
|
redirectViaHome: true,
|
||||||
|
avatars: true,
|
||||||
|
},
|
||||||
|
facebook: {
|
||||||
|
name: 'Facebook',
|
||||||
|
redirectViaHome: true,
|
||||||
|
avatars: false,
|
||||||
|
deprecated: 'https://en.pronouns.page/blog/facebook-login-deprecated',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
BIN
static/img/indieauth-inverse.png
Normal file
BIN
static/img/indieauth-inverse.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
BIN
static/img/indieauth.png
Normal file
BIN
static/img/indieauth.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
10
yarn.lock
10
yarn.lock
@ -8467,6 +8467,16 @@ query-string@^6.13.8:
|
|||||||
split-on-first "^1.0.0"
|
split-on-first "^1.0.0"
|
||||||
strict-uri-encode "^2.0.0"
|
strict-uri-encode "^2.0.0"
|
||||||
|
|
||||||
|
query-string@^7.1.1:
|
||||||
|
version "7.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.1.tgz#754620669db978625a90f635f12617c271a088e1"
|
||||||
|
integrity sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w==
|
||||||
|
dependencies:
|
||||||
|
decode-uri-component "^0.2.0"
|
||||||
|
filter-obj "^1.1.0"
|
||||||
|
split-on-first "^1.0.0"
|
||||||
|
strict-uri-encode "^2.0.0"
|
||||||
|
|
||||||
querystring-es3@^0.2.0:
|
querystring-es3@^0.2.0:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user