summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2019-07-05 18:02:42 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2019-07-05 18:02:42 +0900
commit3c5324bbbb6982d419db76640b46341c3e088543 (patch)
tree534e73fa6f604e726a38f7947663e0899fb0eb05 /src
parentMerge branch 'develop' (diff)
parent11.24.1 (diff)
downloadsharkey-3c5324bbbb6982d419db76640b46341c3e088543.tar.gz
sharkey-3c5324bbbb6982d419db76640b46341c3e088543.tar.bz2
sharkey-3c5324bbbb6982d419db76640b46341c3e088543.zip
Merge branch 'develop'
Diffstat (limited to 'src')
-rw-r--r--src/client/app/common/views/components/emoji.vue16
-rw-r--r--src/client/app/common/views/components/reaction-icon.vue7
-rw-r--r--src/client/app/common/views/components/signin.vue16
-rw-r--r--src/server/api/endpoints/admin/emoji/add.ts3
-rw-r--r--src/server/api/endpoints/admin/emoji/remove.ts3
-rw-r--r--src/server/api/endpoints/admin/emoji/update.ts3
-rw-r--r--src/server/api/endpoints/hashtags/trend.ts11
-rw-r--r--src/server/api/endpoints/i/2fa/getkeys.ts67
-rw-r--r--src/server/api/endpoints/meta.ts2
-rw-r--r--src/server/api/private/signin.ts42
-rw-r--r--src/server/file/send-drive-file.ts2
-rw-r--r--src/services/drive/add-file.ts2
-rw-r--r--src/services/drive/image-processor.ts2
13 files changed, 93 insertions, 83 deletions
diff --git a/src/client/app/common/views/components/emoji.vue b/src/client/app/common/views/components/emoji.vue
index 0cc78a337b..20c1ea1a80 100644
--- a/src/client/app/common/views/components/emoji.vue
+++ b/src/client/app/common/views/components/emoji.vue
@@ -55,6 +55,20 @@ export default Vue.extend({
}
},
+ watch: {
+ customEmojis() {
+ if (this.name) {
+ const customEmoji = this.customEmojis.find(x => x.name == this.name);
+ if (customEmoji) {
+ this.customEmoji = customEmoji;
+ this.url = this.$store.state.device.disableShowingAnimatedImages
+ ? getStaticImageUrl(customEmoji.url)
+ : customEmoji.url;
+ }
+ }
+ },
+ },
+
created() {
if (this.name) {
const customEmoji = this.customEmojis.find(x => x.name == this.name);
@@ -80,7 +94,7 @@ export default Vue.extend({
this.url = `${twemojiBase}/2/svg/${codes.join('-')}.svg`;
}
- }
+ },
});
</script>
diff --git a/src/client/app/common/views/components/reaction-icon.vue b/src/client/app/common/views/components/reaction-icon.vue
index 022d57dc44..afe51d7833 100644
--- a/src/client/app/common/views/components/reaction-icon.vue
+++ b/src/client/app/common/views/components/reaction-icon.vue
@@ -15,9 +15,14 @@ export default Vue.extend({
},
data() {
return {
- customEmojis: (this.$root.getMetaSync() || { emojis: [] }).emojis || []
+ customEmojis: []
};
},
+ created() {
+ this.$root.getMeta().then(meta => {
+ if (meta && meta.emojis) this.customEmojis = meta.emojis;
+ });
+ },
computed: {
str(): any {
switch (this.reaction) {
diff --git a/src/client/app/common/views/components/signin.vue b/src/client/app/common/views/components/signin.vue
index 53cc62c333..8498a1dc3e 100644
--- a/src/client/app/common/views/components/signin.vue
+++ b/src/client/app/common/views/components/signin.vue
@@ -107,9 +107,8 @@ export default Vue.extend({
})),
timeout: 60 * 1000
}
- }).catch(err => {
+ }).catch(() => {
this.queryingKey = false;
- console.warn(err);
return Promise.reject(null);
}).then(credential => {
this.queryingKey = false;
@@ -127,8 +126,7 @@ export default Vue.extend({
localStorage.setItem('i', res.i);
location.reload();
}).catch(err => {
- if(err === null) return;
- console.error(err);
+ if (err === null) return;
this.$root.dialog({
type: 'error',
text: this.$t('login-failed')
@@ -142,7 +140,7 @@ export default Vue.extend({
if (!this.totpLogin && this.user && this.user.twoFactorEnabled) {
if (window.PublicKeyCredential && this.user.securityKeys) {
- this.$root.api('i/2fa/getkeys', {
+ this.$root.api('signin', {
username: this.username,
password: this.password
}).then(res => {
@@ -150,6 +148,14 @@ export default Vue.extend({
this.signing = false;
this.challengeData = res;
return this.queryKey();
+ }).catch(() => {
+ this.$root.dialog({
+ type: 'error',
+ text: this.$t('login-failed')
+ });
+ this.challengeData = null;
+ this.totpLogin = false;
+ this.signing = false;
});
} else {
this.totpLogin = true;
diff --git a/src/server/api/endpoints/admin/emoji/add.ts b/src/server/api/endpoints/admin/emoji/add.ts
index c26e8dd04d..5ba00afde8 100644
--- a/src/server/api/endpoints/admin/emoji/add.ts
+++ b/src/server/api/endpoints/admin/emoji/add.ts
@@ -3,6 +3,7 @@ import define from '../../../define';
import { detectUrlMine } from '../../../../../misc/detect-url-mine';
import { Emojis } from '../../../../../models';
import { genId } from '../../../../../misc/gen-id';
+import { getConnection } from 'typeorm';
export const meta = {
desc: {
@@ -43,6 +44,8 @@ export default define(meta, async (ps) => {
type,
});
+ await getConnection().queryResultCache!.remove(['meta_emojis']);
+
return {
id: emoji.id
};
diff --git a/src/server/api/endpoints/admin/emoji/remove.ts b/src/server/api/endpoints/admin/emoji/remove.ts
index 316834b884..3ebf933bc6 100644
--- a/src/server/api/endpoints/admin/emoji/remove.ts
+++ b/src/server/api/endpoints/admin/emoji/remove.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
import define from '../../../define';
import { ID } from '../../../../../misc/cafy-id';
import { Emojis } from '../../../../../models';
+import { getConnection } from 'typeorm';
export const meta = {
desc: {
@@ -26,4 +27,6 @@ export default define(meta, async (ps) => {
if (emoji == null) throw new Error('emoji not found');
await Emojis.delete(emoji.id);
+
+ await getConnection().queryResultCache!.remove(['meta_emojis']);
});
diff --git a/src/server/api/endpoints/admin/emoji/update.ts b/src/server/api/endpoints/admin/emoji/update.ts
index 48b4a4ee23..f8bc638fcf 100644
--- a/src/server/api/endpoints/admin/emoji/update.ts
+++ b/src/server/api/endpoints/admin/emoji/update.ts
@@ -3,6 +3,7 @@ import define from '../../../define';
import { detectUrlMine } from '../../../../../misc/detect-url-mine';
import { ID } from '../../../../../misc/cafy-id';
import { Emojis } from '../../../../../models';
+import { getConnection } from 'typeorm';
export const meta = {
desc: {
@@ -47,4 +48,6 @@ export default define(meta, async (ps) => {
url: ps.url,
type,
});
+
+ await getConnection().queryResultCache!.remove(['meta_emojis']);
});
diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts
index 3154461e5a..a004732f81 100644
--- a/src/server/api/endpoints/hashtags/trend.ts
+++ b/src/server/api/endpoints/hashtags/trend.ts
@@ -54,8 +54,11 @@ export default define(meta, async () => {
const instance = await fetchMeta(true);
const hiddenTags = instance.hiddenTags.map(t => t.toLowerCase());
+ const now = new Date(); // 5分単位で丸めた現在日時
+ now.setMinutes(Math.round(now.getMinutes() / 5) * 5, 0, 0);
+
const tagNotes = await Notes.createQueryBuilder('note')
- .where(`note.createdAt > :date`, { date: new Date(Date.now() - rangeA) })
+ .where(`note.createdAt > :date`, { date: new Date(now.getTime() - rangeA) })
.andWhere(`note.tags != '{}'`)
.select(['note.tags', 'note.userId'])
.cache(60000) // 1 min
@@ -106,8 +109,8 @@ export default define(meta, async () => {
countPromises.push(Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
.select('count(distinct note.userId)')
.where(':tag = ANY(note.tags)', { tag: tag })
- .andWhere('note.createdAt < :lt', { lt: new Date(Date.now() - (interval * i)) })
- .andWhere('note.createdAt > :gt', { gt: new Date(Date.now() - (interval * (i + 1))) })
+ .andWhere('note.createdAt < :lt', { lt: new Date(now.getTime() - (interval * i)) })
+ .andWhere('note.createdAt > :gt', { gt: new Date(now.getTime() - (interval * (i + 1))) })
.cache(60000) // 1 min
.getRawOne()
.then(x => parseInt(x.count, 10))
@@ -119,7 +122,7 @@ export default define(meta, async () => {
const totalCounts = await Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
.select('count(distinct note.userId)')
.where(':tag = ANY(note.tags)', { tag: tag })
- .andWhere('note.createdAt > :gt', { gt: new Date(Date.now() - (interval * range)) })
+ .andWhere('note.createdAt > :gt', { gt: new Date(now.getTime() - (interval * range)) })
.cache(60000) // 1 min
.getRawOne()
.then(x => parseInt(x.count, 10))
diff --git a/src/server/api/endpoints/i/2fa/getkeys.ts b/src/server/api/endpoints/i/2fa/getkeys.ts
deleted file mode 100644
index bb1585d795..0000000000
--- a/src/server/api/endpoints/i/2fa/getkeys.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import * as crypto from 'crypto';
-import define from '../../../define';
-import { UserProfiles, UserSecurityKeys, AttestationChallenges } from '../../../../../models';
-import { ensure } from '../../../../../prelude/ensure';
-import { promisify } from 'util';
-import { hash } from '../../../2fa';
-import { genId } from '../../../../../misc/gen-id';
-
-export const meta = {
- requireCredential: true,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- }
- }
-};
-
-const randomBytes = promisify(crypto.randomBytes);
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOne(user.id).then(ensure);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- const keys = await UserSecurityKeys.find({
- userId: user.id
- });
-
- if (keys.length === 0) {
- throw new Error('no keys found');
- }
-
- // 32 byte challenge
- const entropy = await randomBytes(32);
- const challenge = entropy.toString('base64')
- .replace(/=/g, '')
- .replace(/\+/g, '-')
- .replace(/\//g, '_');
-
- const challengeId = genId();
-
- await AttestationChallenges.save({
- userId: user.id,
- id: challengeId,
- challenge: hash(Buffer.from(challenge, 'utf-8')).toString('hex'),
- createdAt: new Date(),
- registrationChallenge: false
- });
-
- return {
- challenge,
- challengeId,
- securityKeys: keys.map(key => ({
- id: key.id
- }))
- };
-});
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index a3390a011d..a754a885ab 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -95,7 +95,7 @@ export const meta = {
export default define(meta, async (ps, me) => {
const instance = await fetchMeta(true);
- const emojis = await Emojis.find({ where: { host: null }, cache: 3600000 }); // 1 hour
+ const emojis = await Emojis.find({ where: { host: null }, cache: { id: 'meta_emojis', milliseconds: 3600000 } }); // 1 hour
const response: any = {
maintainerName: instance.maintainerName,
diff --git a/src/server/api/private/signin.ts b/src/server/api/private/signin.ts
index cd9fe5bb9d..bc9346d088 100644
--- a/src/server/api/private/signin.ts
+++ b/src/server/api/private/signin.ts
@@ -9,6 +9,7 @@ import { ILocalUser } from '../../../models/entities/user';
import { genId } from '../../../misc/gen-id';
import { ensure } from '../../../prelude/ensure';
import { verifyLogin, hash } from '../2fa';
+import { randomBytes } from 'crypto';
export default async (ctx: Koa.BaseContext) => {
ctx.set('Access-Control-Allow-Origin', config.url);
@@ -99,7 +100,7 @@ export default async (ctx: Koa.BaseContext) => {
});
return;
}
- } else {
+ } else if (body.credentialId) {
const clientDataJSON = Buffer.from(body.clientDataJSON, 'hex');
const clientData = JSON.parse(clientDataJSON.toString('utf-8'));
const challenge = await AttestationChallenges.findOne({
@@ -131,7 +132,7 @@ export default async (ctx: Koa.BaseContext) => {
const securityKey = await UserSecurityKeys.findOne({
id: Buffer.from(
body.credentialId
- .replace(/\-/g, '+')
+ .replace(/-/g, '+')
.replace(/_/g, '/'),
'base64'
).toString('hex')
@@ -161,7 +162,44 @@ export default async (ctx: Koa.BaseContext) => {
});
return;
}
+ } else {
+ const keys = await UserSecurityKeys.find({
+ userId: user.id
+ });
+
+ if (keys.length === 0) {
+ await fail(403, {
+ error: 'no keys found'
+ });
+ }
+
+ // 32 byte challenge
+ const challenge = randomBytes(32).toString('base64')
+ .replace(/=/g, '')
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_');
+
+ const challengeId = genId();
+
+ await AttestationChallenges.save({
+ userId: user.id,
+ id: challengeId,
+ challenge: hash(Buffer.from(challenge, 'utf-8')).toString('hex'),
+ createdAt: new Date(),
+ registrationChallenge: false
+ });
+
+ ctx.body = {
+ challenge,
+ challengeId,
+ securityKeys: keys.map(key => ({
+ id: key.id
+ }))
+ };
+ ctx.status = 200;
+ return;
}
await fail();
+ return;
};
diff --git a/src/server/file/send-drive-file.ts b/src/server/file/send-drive-file.ts
index 5da3d79eb5..44e88be8ae 100644
--- a/src/server/file/send-drive-file.ts
+++ b/src/server/file/send-drive-file.ts
@@ -42,7 +42,7 @@ export default async function(ctx: Koa.BaseContext) {
ctx.set('Content-Disposition', contentDisposition('inline', `${rename(file.name, { suffix: '-thumb', extname: '.jpeg' })}`));
ctx.body = InternalStorage.read(key);
} else if (isWebpublic) {
- ctx.set('Content-Type', file.type);
+ ctx.set('Content-Type', file.type === 'image/apng' ? 'image/png' : file.type);
ctx.set('Content-Disposition', contentDisposition('inline', `${rename(file.name, { suffix: '-web' })}`));
ctx.body = InternalStorage.read(key);
} else {
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index e7b1e2a812..2f0d5d6265 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -207,6 +207,8 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
* Upload to ObjectStorage
*/
async function upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) {
+ if (type === 'image/apng') type = 'image/png';
+
const meta = await fetchMeta();
const minio = new Minio.Client({
diff --git a/src/services/drive/image-processor.ts b/src/services/drive/image-processor.ts
index 919d9ce138..4b8db0e0c8 100644
--- a/src/services/drive/image-processor.ts
+++ b/src/services/drive/image-processor.ts
@@ -97,6 +97,6 @@ export async function convertToApng(path: string): Promise<IImage> {
return {
data,
ext: 'apng',
- type: 'image/vnd.mozilla.apng'
+ type: 'image/apng'
};
}