mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-20 18:52:10 -04:00
#88 select avatar source
This commit is contained in:
parent
a248bf8667
commit
81d8212786
@ -6,7 +6,13 @@
|
||||
<p class="mb-0">
|
||||
<Avatar :user="$user()"/>
|
||||
</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">
|
||||
<Icon v="external-link"/>
|
||||
<T>user.avatar.change</T>
|
||||
@ -73,7 +79,8 @@
|
||||
</template>
|
||||
<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' : '']">
|
||||
<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>
|
||||
</ul>
|
||||
</Loading>
|
||||
@ -183,6 +190,12 @@
|
||||
|
||||
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>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<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>
|
||||
|
||||
<script>
|
||||
@ -8,9 +9,10 @@
|
||||
export default {
|
||||
props: {
|
||||
user: { required: true },
|
||||
src: {},
|
||||
size: { 'default': 128 },
|
||||
dsize: { 'default': '6rem' },
|
||||
src: {},
|
||||
grav: { type: Boolean },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -12,7 +12,9 @@
|
||||
</span>
|
||||
<span v-else class="text-center">
|
||||
<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}}
|
||||
</span>
|
||||
<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 SQL from 'sql-template-strings';
|
||||
import avatar from '../avatar';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -9,7 +10,7 @@ router.get('/admin/users', async (req, res) => {
|
||||
}
|
||||
|
||||
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
|
||||
LEFT JOIN profiles p ON p.userId = u.id
|
||||
ORDER BY u.id DESC
|
||||
@ -22,6 +23,7 @@ router.get('/admin/users', async (req, res) => {
|
||||
...user,
|
||||
locale: undefined,
|
||||
profiles: user.locale ? [user.locale] : [],
|
||||
avatar: await avatar(req.db, user),
|
||||
}
|
||||
} else {
|
||||
groupedUsers[user.id].profiles.push(user.locale);
|
||||
|
@ -3,6 +3,7 @@ import SQL from 'sql-template-strings';
|
||||
import md5 from "js-md5";
|
||||
import {buildDict} from "../../src/helpers";
|
||||
import {ulid} from "ulid";
|
||||
import avatar from "../avatar";
|
||||
|
||||
const calcAge = birthday => {
|
||||
if (!birthday) {
|
||||
@ -21,41 +22,33 @@ const calcAge = birthday => {
|
||||
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 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}
|
||||
AND profiles.active = 1
|
||||
ORDER BY profiles.locale
|
||||
`);
|
||||
|
||||
return buildDict(function* () {
|
||||
for (let profile of profiles) {
|
||||
yield [
|
||||
profile.locale,
|
||||
{
|
||||
...buildProfile(profile),
|
||||
birthday: self ? profile.birthday : undefined,
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
const p = {}
|
||||
for (let profile of profiles) {
|
||||
p[profile.locale] = {
|
||||
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),
|
||||
avatar: await avatar(db, profile),
|
||||
birthday: self ? profile.birthday : undefined,
|
||||
};
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
const router = Router();
|
||||
|
@ -6,6 +6,7 @@ import translations from "../translations";
|
||||
import jwt from "../../src/jwt";
|
||||
import mailer from "../../src/mailer";
|
||||
import config from '../config';
|
||||
import avatar from '../avatar';
|
||||
|
||||
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)}`);
|
||||
if (!dbUser) {
|
||||
dbUser = {
|
||||
@ -71,12 +72,14 @@ const fetchOrCreateUser = async (db, user) => {
|
||||
username: await defaultUsername(db, user.name || user.email),
|
||||
email: normalise(user.email),
|
||||
roles: 'user',
|
||||
avatarSource: null,
|
||||
avatarSource: avatarSource,
|
||||
}
|
||||
await db.get(SQL`INSERT INTO users(id, username, email, roles, avatarSource)
|
||||
VALUES (${dbUser.id}, ${dbUser.username}, ${dbUser.email}, ${dbUser.roles}, ${dbUser.avatarSource})`)
|
||||
}
|
||||
|
||||
dbUser.avatar = await avatar(db, dbUser);
|
||||
|
||||
return dbUser;
|
||||
}
|
||||
|
||||
@ -255,7 +258,6 @@ const socialLoginHandlers = {
|
||||
}
|
||||
},
|
||||
facebook(r) {
|
||||
console.log(r);
|
||||
return {
|
||||
id: r.profile.id,
|
||||
email: r.profile.email,
|
||||
@ -266,7 +268,6 @@ const socialLoginHandlers = {
|
||||
}
|
||||
},
|
||||
google(r) {
|
||||
console.log(r);
|
||||
return {
|
||||
id: r.profile.sub,
|
||||
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 || {
|
||||
email: payload.email || `${payload.id}@${req.params.provider}.oauth`,
|
||||
name: payload.name,
|
||||
});
|
||||
}, req.params.provider);
|
||||
|
||||
const token = jwt.sign({
|
||||
...dbUser,
|
||||
@ -347,4 +348,18 @@ router.post('/user/social-connection/:provider/disconnect', async (req, res) =>
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user