Skip to content

Commit

Permalink
Release 2022.07.03-milkey-2.8 (#72)
Browse files Browse the repository at this point in the history
* Add CI to pull request

* Node 16.20.2

* Fix: Apply Streaming on Unrenote

Fix: Apply Streaming on Unrenote

Fix: Apply Streaming on Unrenote

Fix: Apply Streaming on Unrenote

Fix: Apply Streaming on Unrenote

* fix polls update localonly

* noteActivity null check

* Change deliver retryable statusCode

* Fix: users/show response wrong users

* Fix: admin/annoucements

・画像URLを空にできるように
・追加してすぐ更新しても増殖しないように
・10件よりも多く表示できるように

* as:Public

* Fix: user list timeline

* Fix: Blocked Host not to generate query if not exist

* Update sharp, systeminformation

* Fix: HTTP signature validation

Fix: HTTP signature validation

Fix: http signature

Fix: http signature

Fix: http signature

Fix: http signature

* fix: Filter featured collection

* Fix: also send delete activity of cascaded notes to stream

* feat: リモートからユーザー削除が飛んできたら削除するように

Delete Actor

* Fix Announce/Delete AP deliver

* Fix: API admin permission

* Fix: Renote pure renote

* Renote Visibility Check

* 2022.07.03-milkey-2.8
  • Loading branch information
atsu1125 authored Dec 27, 2023
1 parent 3d2ed1c commit 35eafcb
Show file tree
Hide file tree
Showing 32 changed files with 361 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dockerimage.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Docker Image CI

on: [push]
on: [push, pull_request, release]

jobs:
build:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Node.js CI
on: [push]
on: [push, pull_request, release]

jobs:
build_and_test:
Expand Down
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v16.19.1
v16.20.2
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16.19.1-bullseye AS builder
FROM node:16.20.2-bullseye AS builder

ENV NODE_ENV=production
WORKDIR /misskey
Expand All @@ -12,7 +12,7 @@ COPY . ./
RUN yarn build


FROM node:16.19.1-bullseye-slim AS runner
FROM node:16.20.2-bullseye-slim AS runner

WORKDIR /misskey

Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "groundpolis-milkey",
"version": "2022.07.03-milkey-2.7",
"version": "2022.07.03-milkey-2.8",
"private": true,
"author": "Xeltica <[email protected]> , Minemu <[email protected]> , Azuki⪥ <[email protected]> , Remito <[email protected]> , atsu1125 <[email protected]>",
"contributors": [
Expand Down Expand Up @@ -54,6 +54,7 @@
"@koa/cors": "3.1.0",
"@koa/multer": "3.0.0",
"@koa/router": "9.0.1",
"@peertube/http-signature": "1.7.0",
"@sentry/browser": "7.5.1",
"@sentry/tracing": "5.29.2",
"@sinonjs/fake-timers": "10.0.0",
Expand Down Expand Up @@ -228,13 +229,13 @@
"sass": "1.49.9",
"sass-loader": "13.2.0",
"seedrandom": "3.0.5",
"sharp": "0.31.1",
"sharp": "0.32.6",
"speakeasy": "2.0.0",
"stringz": "2.1.0",
"style-loader": "3.3.1",
"summaly": "2.7.0",
"syslog-pro": "1.0.0",
"systeminformation": "5.12.6",
"systeminformation": "5.21.7",
"syuilo-password-strength": "0.0.1",
"terser-webpack-plugin": "4.2.3",
"textarea-caret": "3.1.0",
Expand Down
8 changes: 7 additions & 1 deletion src/client/components/note-detailed.vue
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ export default defineComponent({
capture(withHandler = false) {
if (this.$i) {
this.connection.send(document.body.contains(this.$el) ? 'sn' : 's', { id: this.appearNote.id });
if (this.note.id !== this.appearNote.id) this.connection.send('s', { id: this.note.id });
if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated);
}
},
Expand All @@ -404,6 +405,11 @@ export default defineComponent({
this.connection.send('un', {
id: this.appearNote.id
});
if (this.note.id !== this.appearNote.id) {
this.connection.send('un', {
id: this.note.id,
});
}
if (withHandler) this.connection.off('noteUpdated', this.onStreamNoteUpdated);
}
},
Expand All @@ -415,7 +421,7 @@ export default defineComponent({
onStreamNoteUpdated(data) {
const { type, id, body } = data;
if (id !== this.appearNote.id) return;
if ((id !== this.note.id) && (id !== this.appearNote.id)) return;
switch (type) {
case 'reacted': {
Expand Down
10 changes: 8 additions & 2 deletions src/client/components/note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export default defineComponent({
},
canRenote(): boolean {
return ['public', 'home'].includes(this.appearNote.visibility) || this.isMyNote;
return ['public', 'home'].includes(this.appearNote.visibility) || (['followers', 'users'].includes(this.appearNote.visibility) && this.isMyNote);
},
reactionsCount(): number {
Expand Down Expand Up @@ -385,6 +385,7 @@ export default defineComponent({
capture(withHandler = false) {
if (this.$i) {
this.connection.send(document.body.contains(this.$el) ? 'sn' : 's', { id: this.appearNote.id });
if (this.note.id !== this.appearNote.id) this.connection.send('s', { id: this.note.id });
if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated);
}
},
Expand All @@ -394,6 +395,11 @@ export default defineComponent({
this.connection.send('un', {
id: this.appearNote.id
});
if (this.note.id !== this.appearNote.id) {
this.connection.send('un', {
id: this.note.id,
});
}
if (withHandler) this.connection.off('noteUpdated', this.onStreamNoteUpdated);
}
},
Expand All @@ -405,7 +411,7 @@ export default defineComponent({
onStreamNoteUpdated(data) {
const { type, id, body } = data;
if (id !== this.appearNote.id) return;
if ((id !== this.note.id) && (id !== this.appearNote.id)) return;
switch (type) {
case 'reacted': {
Expand Down
20 changes: 18 additions & 2 deletions src/client/pages/instance/announcements.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
</div>
</div>
</section>
<MkButton class="button" inline @click="more()"><Fa :icon="faEllipsisH"/> {{ $ts.more }}</MkButton>
</div>
</div>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { faBroadcastTower, faPlus } from '@fortawesome/free-solid-svg-icons';
import { faBroadcastTower, faPlus, faEllipsisH } from '@fortawesome/free-solid-svg-icons';
import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons';
import MkButton from '@/components/ui/button.vue';
import MkInput from '@/components/ui/input.vue';
Expand All @@ -52,7 +53,7 @@ export default defineComponent({
},
},
announcements: [],
faBroadcastTower, faSave, faTrashAlt
faBroadcastTower, faSave, faTrashAlt, faEllipsisH
}
},
Expand Down Expand Up @@ -91,6 +92,7 @@ export default defineComponent({
type: 'success',
text: this.$ts.saved
});
this.refresh();
}).catch(e => {
os.dialog({
type: 'error',
Expand All @@ -110,6 +112,20 @@ export default defineComponent({
});
});
}
},
refresh() {
os.api('admin/announcements/list').then(announcements => {
this.announcements = announcements;
});
},
more() {
const announcements = this.announcements;
os.api('admin/announcements/list', { untilId: announcements.reduce((acc, announcement) => announcement.id != null ? announcement : acc).id }).then(announcements => {
this.announcements = this.announcements.concat(announcements);
});
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/queue/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Queue from 'bull';
import * as httpSignature from 'http-signature';
import * as httpSignature from '@peertube/http-signature';

import config from '../config';
import { ILocalUser } from '../models/entities/user';
Expand Down
9 changes: 9 additions & 0 deletions src/queue/processors/deliver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,20 @@ export default async (job: Bull.Job) => {
if (res != null && res.hasOwnProperty('statusCode')) {
// 4xx
if (res.statusCode >= 400 && res.statusCode < 500) {
// 401,408,429がどうもpermanent errorじゃなさそう
if (res.statusCode === 401 || res.statusCode === 408 || res.statusCode === 429) {
throw `${res.statusCode} ${res.statusMessage}`;
}
// HTTPステータスコード4xxはクライアントエラーであり、それはつまり
// 何回再送しても成功することはないということなのでエラーにはしないでおく
return `${res.statusCode} ${res.statusMessage}`;
}

// ただし501は成功することはない
if (res.statusCode === 501) {
return `${res.statusCode} ${res.statusMessage}`;
}

// 5xx etc.
throw `${res.statusCode} ${res.statusMessage}`;
} else {
Expand Down
7 changes: 6 additions & 1 deletion src/queue/processors/inbox.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Bull from 'bull';
import * as httpSignature from 'http-signature';
import * as httpSignature from '@peertube/http-signature';
import perform from '../../remote/activitypub/perform';
import Logger from '../../services/logger';
import { registerOrFetchInstanceDoc } from '../../services/register-or-fetch-instance-doc';
Expand All @@ -13,6 +13,7 @@ import { InboxJobData } from '..';
import DbResolver from '../../remote/activitypub/db-resolver';
import { resolvePerson } from '../../remote/activitypub/models/person';
import { LdSignature } from '../../remote/activitypub/misc/ld-signature';
import { verifySignature } from '../../remote/activitypub/check-fetch.js';

const logger = new Logger('inbox');

Expand Down Expand Up @@ -66,6 +67,10 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
// HTTP-Signatureの検証
const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem);

if (httpSignatureValidated) {
if (!verifySignature(signature, authUser.key)) return `skip: Invalid HTTP signature`;
}

// また、signatureのsignerは、activity.actorと一致する必要がある
if (!httpSignatureValidated || authUser.user.uri !== activity.actor) {
// 一致しなくても、でもLD-Signatureがありそうならそっちも見る
Expand Down
2 changes: 1 addition & 1 deletion src/queue/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DriveFile } from '../models/entities/drive-file';
import { User } from '../models/entities/user';
import { IActivity } from '../remote/activitypub/type';
import * as httpSignature from 'http-signature';
import * as httpSignature from '@peertube/http-signature';

export type DeliverJobData = {
/** Actor */
Expand Down
2 changes: 1 addition & 1 deletion src/remote/activitypub/audience.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function groupingAudience(ids: string[], actor: IRemoteUser) {
function isPublic(id: string) {
return [
'https://www.w3.org/ns/activitystreams#Public',
'as#Public',
'as:Public',
'Public',
].includes(id);
}
Expand Down
23 changes: 23 additions & 0 deletions src/remote/activitypub/check-fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IParsedSignature } from '@peertube/http-signature';
import { verify } from 'crypto';
import { createHash } from 'crypto';
import { toSingle } from '../../prelude/array';

export function verifySignature(sig: IParsedSignature, key: UserPublickey): boolean {
if (!['hs2019', 'rsa-sha256'].includes(sig.algorithm.toLowerCase())) return false;
try {
return verify('rsa-sha256', Buffer.from(sig.signingString, 'utf8'), key.keyPem, Buffer.from(sig.params.signature, 'base64'));
}
catch {
// Algo not supported
return false;
}
}

export function verifyDigest(body: string, digest: string | string[] | undefined): boolean {
digest = toSingle(digest);
if (body == null || digest == null || !digest.toLowerCase().startsWith('sha-256='))
return false;

return createHash('sha256').update(body).digest('base64') === digest.substring(8);
}
26 changes: 26 additions & 0 deletions src/remote/activitypub/kernel/delete/actor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { apLogger } from '../../logger';
import { createDeleteAccountJob } from '../../../../queue';
import { IRemoteUser } from '../../../../models/entities/user';
import { Users } from '../../../../models/index';

const logger = apLogger;

export async function deleteActor(actor: IRemoteUser, uri: string): Promise<string> {
logger.info(`Deleting the Actor: ${uri}`);

if (actor.uri !== uri) {
return `skip: delete actor ${actor.uri} !== ${uri}`;
}

if (actor.isDeleted) {
logger.info(`skip: already deleted`);
}

const job = await createDeleteAccountJob(actor);

await Users.update(actor.id, {
isDeleted: true,
});

return `ok: queued ${job.name} ${job.id}`;
}
3 changes: 2 additions & 1 deletion src/remote/activitypub/kernel/delete/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import deleteNote from './note';
import { IRemoteUser } from '../../../../models/entities/user';
import { IDelete, getApId, isTombstone, IObject, validPost, validActor } from '../../type';
import { toSingle } from '../../../../prelude/array';
import { deleteActor } from './actor';

/**
* 削除アクティビティを捌きます
Expand Down Expand Up @@ -41,7 +42,7 @@ export default async (actor: IRemoteUser, activity: IDelete): Promise<string> =>
if (validPost.includes(formarType)) {
return await deleteNote(actor, uri);
} else if (validActor.includes(formarType)) {
return `Delete Actor is not implanted`;
return await deleteActor(actor, uri);
} else {
return `Unknown type ${formarType}`;
}
Expand Down
14 changes: 9 additions & 5 deletions src/remote/activitypub/renderer/undo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import config from '../../../config';
import { ILocalUser, User } from '../../../models/entities/user';

export default (object: any, user: ILocalUser | User) => ({
type: 'Undo',
actor: `${config.url}/users/${user.id}`,
object
});
export default (object: any, user: ILocalUser | User) => {
if (object == null) return null;

return {
type: 'Undo',
actor: `${config.url}/users/${user.id}`,
object
};
};
Loading

0 comments on commit 35eafcb

Please sign in to comment.