mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-24 05:05:20 -04:00
#88 select avatar source
This commit is contained in:
parent
a248bf8667
commit
81d8212786
@ -6,7 +6,13 @@
|
|||||||
<p class="mb-0">
|
<p class="mb-0">
|
||||||
<Avatar :user="$user()"/>
|
<Avatar :user="$user()"/>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p v-if="$user().avatarSource" class="mt-3">
|
||||||
|
Gravatar:
|
||||||
|
<a href="#" @click.prevent="setAvatar(null)">
|
||||||
|
<Avatar :user="$user()" grav dsize="2rem"/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p v-else>
|
||||||
<a href="https://gravatar.com" target="_blank" rel="noopener" class="small">
|
<a href="https://gravatar.com" target="_blank" rel="noopener" class="small">
|
||||||
<Icon v="external-link"/>
|
<Icon v="external-link"/>
|
||||||
<T>user.avatar.change</T>
|
<T>user.avatar.change</T>
|
||||||
@ -73,7 +79,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<ul v-if="socialConnections !== undefined" class="list-group">
|
<ul v-if="socialConnections !== undefined" class="list-group">
|
||||||
<li v-for="(providerOptions, provider) in socialProviders" :key="provider" :class="['list-group-item', 'en' === config.locale ? 'profile-current' : '']">
|
<li v-for="(providerOptions, provider) in socialProviders" :key="provider" :class="['list-group-item', 'en' === config.locale ? 'profile-current' : '']">
|
||||||
<SocialConnection :provider="provider" :providerOptions="providerOptions" :connection="socialConnections[provider]" @disconnected="socialConnections[provider] = undefined"/>
|
<SocialConnection :provider="provider" :providerOptions="providerOptions" :connection="socialConnections[provider]"
|
||||||
|
@disconnected="socialConnections[provider] = undefined" @setAvatar="setAvatar"/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Loading>
|
</Loading>
|
||||||
@ -183,6 +190,12 @@
|
|||||||
|
|
||||||
this.logout();
|
this.logout();
|
||||||
},
|
},
|
||||||
|
async setAvatar(source) {
|
||||||
|
const response = await this.$axios.$post(`/user/set-avatar`, {source});
|
||||||
|
|
||||||
|
this.$store.commit('setToken', response.token);
|
||||||
|
this.$cookies.set('token', this.$store.state.token);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<img :src="src || gravatar" alt="" class="rounded-circle" :style="`width: 100%;max-width: ${dsize};max-height: ${dsize};`"/>
|
<img :src="grav ? gravatar : (src || user.avatar || gravatar)" alt="" class="rounded-circle"
|
||||||
|
:style="`width: 100%;max-width: ${dsize};max-height: ${dsize};`"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -8,9 +9,10 @@
|
|||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
user: { required: true },
|
user: { required: true },
|
||||||
|
src: {},
|
||||||
size: { 'default': 128 },
|
size: { 'default': 128 },
|
||||||
dsize: { 'default': '6rem' },
|
dsize: { 'default': '6rem' },
|
||||||
src: {},
|
grav: { type: Boolean },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
</span>
|
</span>
|
||||||
<span v-else class="text-center">
|
<span v-else class="text-center">
|
||||||
<span class="mr-3">
|
<span class="mr-3">
|
||||||
<Avatar :src="connection.avatar" :user="$user()" dsize="2rem"/>
|
<a href="#" @click.prevent="$emit('setAvatar', provider)">
|
||||||
|
<Avatar :src="connection.avatar" :user="$user()" dsize="2rem"/>
|
||||||
|
</a>
|
||||||
{{connection.name}}
|
{{connection.name}}
|
||||||
</span>
|
</span>
|
||||||
<br class="d-md-none"/>
|
<br class="d-md-none"/>
|
||||||
|
20
server/avatar.js
Normal file
20
server/avatar.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {gravatar} from "../src/helpers";
|
||||||
|
import SQL from "sql-template-strings";
|
||||||
|
|
||||||
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
|
export default async (db, user) => {
|
||||||
|
if (user.avatarSource) {
|
||||||
|
const auth = await db.get(SQL`
|
||||||
|
SELECT payload FROM authenticators
|
||||||
|
WHERE type = ${user.avatarSource}
|
||||||
|
AND userId = ${user.id}
|
||||||
|
AND (validUntil IS NULL OR validUntil > ${now})
|
||||||
|
`)
|
||||||
|
if (auth) {
|
||||||
|
return JSON.parse(auth.payload).avatar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gravatar(user);
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import SQL from 'sql-template-strings';
|
import SQL from 'sql-template-strings';
|
||||||
|
import avatar from '../avatar';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ router.get('/admin/users', async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const users = await req.db.all(SQL`
|
const users = await req.db.all(SQL`
|
||||||
SELECT u.id, u.username, u.email, u.roles, p.locale
|
SELECT u.id, u.username, u.email, u.roles, u.avatarSource, p.locale
|
||||||
FROM users u
|
FROM users u
|
||||||
LEFT JOIN profiles p ON p.userId = u.id
|
LEFT JOIN profiles p ON p.userId = u.id
|
||||||
ORDER BY u.id DESC
|
ORDER BY u.id DESC
|
||||||
@ -22,6 +23,7 @@ router.get('/admin/users', async (req, res) => {
|
|||||||
...user,
|
...user,
|
||||||
locale: undefined,
|
locale: undefined,
|
||||||
profiles: user.locale ? [user.locale] : [],
|
profiles: user.locale ? [user.locale] : [],
|
||||||
|
avatar: await avatar(req.db, user),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
groupedUsers[user.id].profiles.push(user.locale);
|
groupedUsers[user.id].profiles.push(user.locale);
|
||||||
|
@ -3,6 +3,7 @@ import SQL from 'sql-template-strings';
|
|||||||
import md5 from "js-md5";
|
import md5 from "js-md5";
|
||||||
import {buildDict} from "../../src/helpers";
|
import {buildDict} from "../../src/helpers";
|
||||||
import {ulid} from "ulid";
|
import {ulid} from "ulid";
|
||||||
|
import avatar from "../avatar";
|
||||||
|
|
||||||
const calcAge = birthday => {
|
const calcAge = birthday => {
|
||||||
if (!birthday) {
|
if (!birthday) {
|
||||||
@ -21,41 +22,33 @@ const calcAge = birthday => {
|
|||||||
return parseInt(Math.floor(diff / 1000 / 60 / 60 / 24 / 365.25));
|
return parseInt(Math.floor(diff / 1000 / 60 / 60 / 24 / 365.25));
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildProfile = profile => {
|
|
||||||
return {
|
|
||||||
id: profile.id,
|
|
||||||
userId: profile.userId,
|
|
||||||
username: profile.username,
|
|
||||||
emailHash: md5(profile.email),
|
|
||||||
names: JSON.parse(profile.names),
|
|
||||||
pronouns: JSON.parse(profile.pronouns),
|
|
||||||
description: profile.description,
|
|
||||||
age: calcAge(profile.birthday),
|
|
||||||
links: JSON.parse(profile.links),
|
|
||||||
flags: JSON.parse(profile.flags),
|
|
||||||
words: JSON.parse(profile.words),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchProfiles = async (db, username, self) => {
|
const fetchProfiles = async (db, username, self) => {
|
||||||
const profiles = await db.all(SQL`
|
const profiles = await db.all(SQL`
|
||||||
SELECT profiles.*, users.username, users.email FROM profiles LEFT JOIN users on users.id == profiles.userId
|
SELECT profiles.*, users.id, users.username, users.email, users.avatarSource FROM profiles LEFT JOIN users on users.id == profiles.userId
|
||||||
WHERE users.username = ${username}
|
WHERE users.username = ${username}
|
||||||
AND profiles.active = 1
|
AND profiles.active = 1
|
||||||
ORDER BY profiles.locale
|
ORDER BY profiles.locale
|
||||||
`);
|
`);
|
||||||
|
|
||||||
return buildDict(function* () {
|
const p = {}
|
||||||
for (let profile of profiles) {
|
for (let profile of profiles) {
|
||||||
yield [
|
p[profile.locale] = {
|
||||||
profile.locale,
|
id: profile.id,
|
||||||
{
|
userId: profile.userId,
|
||||||
...buildProfile(profile),
|
username: profile.username,
|
||||||
birthday: self ? profile.birthday : undefined,
|
emailHash: md5(profile.email),
|
||||||
}
|
names: JSON.parse(profile.names),
|
||||||
];
|
pronouns: JSON.parse(profile.pronouns),
|
||||||
}
|
description: profile.description,
|
||||||
});
|
age: calcAge(profile.birthday),
|
||||||
|
links: JSON.parse(profile.links),
|
||||||
|
flags: JSON.parse(profile.flags),
|
||||||
|
words: JSON.parse(profile.words),
|
||||||
|
avatar: await avatar(db, profile),
|
||||||
|
birthday: self ? profile.birthday : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
@ -6,6 +6,7 @@ import translations from "../translations";
|
|||||||
import jwt from "../../src/jwt";
|
import jwt from "../../src/jwt";
|
||||||
import mailer from "../../src/mailer";
|
import mailer from "../../src/mailer";
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
import avatar from '../avatar';
|
||||||
|
|
||||||
const now = Math.floor(Date.now() / 1000);
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ const defaultUsername = async (db, email) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchOrCreateUser = async (db, user) => {
|
const fetchOrCreateUser = async (db, user, avatarSource = null) => {
|
||||||
let dbUser = await db.get(SQL`SELECT * FROM users WHERE email = ${normalise(user.email)}`);
|
let dbUser = await db.get(SQL`SELECT * FROM users WHERE email = ${normalise(user.email)}`);
|
||||||
if (!dbUser) {
|
if (!dbUser) {
|
||||||
dbUser = {
|
dbUser = {
|
||||||
@ -71,12 +72,14 @@ const fetchOrCreateUser = async (db, user) => {
|
|||||||
username: await defaultUsername(db, user.name || user.email),
|
username: await defaultUsername(db, user.name || user.email),
|
||||||
email: normalise(user.email),
|
email: normalise(user.email),
|
||||||
roles: 'user',
|
roles: 'user',
|
||||||
avatarSource: null,
|
avatarSource: avatarSource,
|
||||||
}
|
}
|
||||||
await db.get(SQL`INSERT INTO users(id, username, email, roles, avatarSource)
|
await db.get(SQL`INSERT INTO users(id, username, email, roles, avatarSource)
|
||||||
VALUES (${dbUser.id}, ${dbUser.username}, ${dbUser.email}, ${dbUser.roles}, ${dbUser.avatarSource})`)
|
VALUES (${dbUser.id}, ${dbUser.username}, ${dbUser.email}, ${dbUser.roles}, ${dbUser.avatarSource})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbUser.avatar = await avatar(db, dbUser);
|
||||||
|
|
||||||
return dbUser;
|
return dbUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +258,6 @@ const socialLoginHandlers = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
facebook(r) {
|
facebook(r) {
|
||||||
console.log(r);
|
|
||||||
return {
|
return {
|
||||||
id: r.profile.id,
|
id: r.profile.id,
|
||||||
email: r.profile.email,
|
email: r.profile.email,
|
||||||
@ -266,7 +268,6 @@ const socialLoginHandlers = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
google(r) {
|
google(r) {
|
||||||
console.log(r);
|
|
||||||
return {
|
return {
|
||||||
id: r.profile.sub,
|
id: r.profile.sub,
|
||||||
email: r.profile.email_verified !== false ? r.profile.email : undefined,
|
email: r.profile.email_verified !== false ? r.profile.email : undefined,
|
||||||
@ -296,7 +297,7 @@ router.get('/user/social/:provider', async (req, res) => {
|
|||||||
const dbUser = await fetchOrCreateUser(req.db, user || {
|
const dbUser = await fetchOrCreateUser(req.db, user || {
|
||||||
email: payload.email || `${payload.id}@${req.params.provider}.oauth`,
|
email: payload.email || `${payload.id}@${req.params.provider}.oauth`,
|
||||||
name: payload.name,
|
name: payload.name,
|
||||||
});
|
}, req.params.provider);
|
||||||
|
|
||||||
const token = jwt.sign({
|
const token = jwt.sign({
|
||||||
...dbUser,
|
...dbUser,
|
||||||
@ -347,4 +348,18 @@ router.post('/user/social-connection/:provider/disconnect', async (req, res) =>
|
|||||||
return res.json('ok');
|
return res.json('ok');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/user/set-avatar', async (req, res) => {
|
||||||
|
if (!req.user) {
|
||||||
|
return res.status(401).json({error: 'Unauthorised'});
|
||||||
|
}
|
||||||
|
|
||||||
|
await req.db.get(SQL`
|
||||||
|
UPDATE users
|
||||||
|
SET avatarSource = ${req.body.source || null}
|
||||||
|
WHERE id = ${req.user.id}
|
||||||
|
`)
|
||||||
|
|
||||||
|
return res.json({token: await issueAuthentication(req.db, req.user)});
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user