Merge branch 'develop' into refactor/push-notification

This commit is contained in:
naskya 2024-04-30 06:53:29 +09:00
commit c13d6344e1
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
22 changed files with 110 additions and 71 deletions

View file

@ -5,18 +5,20 @@ Critical security updates are indicated by the :warning: icon.
- Server administrators should check [notice-for-admins.md](./notice-for-admins.md) as well.
- Third-party client/bot developers may want to check [api-change.md](./api-change.md) as well.
## Unreleased
## :warning: [v20240430](https://firefish.dev/firefish/firefish/-/merge_requests/10781/commits)
- Add ability to group similar notifications
- Add features to share links to an account in the three dots menu on the profile page
- Improve server logs
- Fix bugs
- Fix bugs (including a critical security issue)
- We are very thankful to @tesaguri and Laura Hausmann for helping to fix the security issue.
## [v20240424](https://firefish.dev/firefish/firefish/-/merge_requests/10765/commits)
- Improve the usability of the feature to prevent forgetting to write alt texts
- Add a server-wide setting for the maximum number of antennas each user can create
- Fix bugs
- Fix bugs (including a medium sevirity security issue)
- We are very thankful to @mei23 for kindly sharing the information about the security issue.
## [v20240421](https://firefish.dev/firefish/firefish/-/merge_requests/10756/commits)

View file

@ -2,12 +2,33 @@
You can skip intermediate versions when upgrading from an old version, but please read the notices and follow the instructions for each intermediate version before [upgrading](./upgrade.md).
## Unreleased
## v20240430
### For all users
You can control the verbosity of the server log by adding `maxLogLevel` in `.config/default.yml`. `logLevels` has been deprecated in favor of this setting. (see also: <https://firefish.dev/firefish/firefish/-/blob/eac0c1c47cd23789dcc395ab08b074934409fd96/.config/example.yml#L152>)
### For systemd/pm2 users
Not only Firefish but also Node.js has recently fixed a few security issues:
- https://nodejs.org/en/blog/vulnerability/april-2024-security-releases
- https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
So, it is highly recommended that you upgrade your Node.js version as well. The new versions are
- Node v18.20.2 (v18.x LTS)
- Node v20.12.2 (v20.x LTS)
- Node v21.7.3 (v21.x)
You can check your Node.js version by this command:
```sh
node --version
```
[Node v22](https://nodejs.org/en/blog/announcements/v22-release-announce) was also released several days ago, but we have not yet tested Firefish with this version.
## v20240413
### For all users

View file

@ -2300,3 +2300,4 @@ inputAccountId: Sisplau introdueix el teu compte (per exemple @firefish@info.fir
getQrCode: Mostrar el codi QR
copyRemoteFollowUrl: Còpia la adreça URL del seguidor remot
foldNotification: Agrupar les notificacions similars
slashQuote: Cita encadenada

View file

@ -2278,3 +2278,4 @@ cannotEditVisibility: Kamu tidak bisa menyunting keterlihatan
useThisAccountConfirm: Apakah kamu ingin melanjutkan dengan akun ini?
inputAccountId: Silakan memasukkan akunmu (misalnya, @firefish@info.firefish.dev)
copyRemoteFollowUrl: Salin URL ikuti jarak jauh
slashQuote: Kutipan rantai

View file

@ -2067,3 +2067,4 @@ useThisAccountConfirm: このアカウントで操作を続けますか?
getQrCode: QRコードを表示
copyRemoteFollowUrl: リモートからフォローするURLをコピー
foldNotification: 同じ種類の通知をまとめて表示する
slashQuote: 繋げて引用

View file

@ -1,6 +1,6 @@
{
"name": "firefish",
"version": "20240424",
"version": "20240430",
"repository": {
"type": "git",
"url": "https://firefish.dev/firefish/firefish.git"

View file

@ -24,7 +24,7 @@ const logger = new Logger("inbox");
// Processing when an activity arrives in the user's inbox
export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
const signature = job.data.signature; // HTTP-signature
const activity = job.data.activity;
let activity = job.data.activity;
//#region Log
const info = Object.assign({}, activity) as any;
@ -149,6 +149,8 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
return "skip: LD-Signatureの検証に失敗しました";
}
activity = await ldSignature.compactToWellKnown(activity);
// もう一度actorチェック
if (authUser.user.uri !== activity.actor) {
return `skip: LD-Signature user(${authUser.user.uri}) !== activity.actor(${activity.actor})`;

View file

@ -518,6 +518,54 @@ const activitystreams = {
},
};
export const WellKnownContext = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
// as non-standards
manuallyApprovesFollowers: "as:manuallyApprovesFollowers",
movedTo: {
"@id": "https://www.w3.org/ns/activitystreams#movedTo",
"@type": "@id"
},
movedToUri: "as:movedTo",
sensitive: "as:sensitive",
Hashtag: "as:Hashtag",
quoteUri: "fedibird:quoteUri",
quoteUrl: "as:quoteUrl",
// Mastodon
toot: "http://joinmastodon.org/ns#",
Emoji: "toot:Emoji",
featured: "toot:featured",
discoverable: "toot:discoverable",
indexable: "toot:indexable",
// schema
schema: "http://schema.org#",
PropertyValue: "schema:PropertyValue",
value: "schema:value",
// Firefish
firefish: "https://firefish.dev/ns#",
speakAsCat: "firefish:speakAsCat",
// Misskey
misskey: "https://misskey-hub.net/ns#",
_misskey_talk: "misskey:_misskey_talk",
_misskey_reaction: "misskey:_misskey_reaction",
_misskey_votes: "misskey:_misskey_votes",
_misskey_summary: "misskey:_misskey_summary",
isCat: "misskey:isCat",
// Fedibird
fedibird: "http://fedibird.com/ns#",
// vcard
vcard: "http://www.w3.org/2006/vcard/ns#",
// litepub
litepub: "http://litepub.social/ns#",
ChatMessage: "litepub:ChatMessage",
directMessage: "litepub:directMessage",
},
],
};
export const CONTEXTS: Record<string, unknown> = {
"https://w3id.org/identity/v1": id_v1,
"https://w3id.org/security/v1": security_v1,

View file

@ -1,6 +1,6 @@
import * as crypto from "node:crypto";
import jsonld from "jsonld";
import { CONTEXTS } from "./contexts.js";
import { CONTEXTS, WellKnownContext } from "./contexts.js";
import fetch from "node-fetch";
import { httpAgent, httpsAgent } from "@/misc/fetch.js";
@ -89,6 +89,13 @@ export class LdSignature {
});
}
public async compactToWellKnown(data: any): Promise<any> {
const options = { documentLoader: this.getLoader() };
const context = WellKnownContext as any;
delete data["signature"];
return await jsonld.compact(data, context, options);
}
private getLoader() {
return async (url: string): Promise<any> => {
if (!url.match("^https?://")) throw new Error(`Invalid URL ${url}`);

View file

@ -4,6 +4,7 @@ import { getUserKeypair } from "@/misc/keypair-store.js";
import type { User } from "@/models/entities/user.js";
import { LdSignature } from "../misc/ld-signature.js";
import type { IActivity } from "../type.js";
import { WellKnownContext } from "@/remote/activitypub/misc/contexts.js";
export const renderActivity = (x: any): IActivity | null => {
if (x == null) return null;
@ -12,52 +13,7 @@ export const renderActivity = (x: any): IActivity | null => {
x.id = `${config.url}/${uuid()}`;
}
return Object.assign(
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
// as non-standards
manuallyApprovesFollowers: "as:manuallyApprovesFollowers",
movedToUri: "as:movedTo",
sensitive: "as:sensitive",
Hashtag: "as:Hashtag",
quoteUri: "fedibird:quoteUri",
quoteUrl: "as:quoteUrl",
// Mastodon
toot: "http://joinmastodon.org/ns#",
Emoji: "toot:Emoji",
featured: "toot:featured",
discoverable: "toot:discoverable",
indexable: "toot:indexable",
// schema
schema: "http://schema.org#",
PropertyValue: "schema:PropertyValue",
value: "schema:value",
// Firefish
firefish: "https://firefish.dev/ns#",
speakAsCat: "firefish:speakAsCat",
// Misskey
misskey: "https://misskey-hub.net/ns#",
_misskey_talk: "misskey:_misskey_talk",
_misskey_reaction: "misskey:_misskey_reaction",
_misskey_votes: "misskey:_misskey_votes",
_misskey_summary: "misskey:_misskey_summary",
isCat: "misskey:isCat",
// Fedibird
fedibird: "http://fedibird.com/ns#",
// vcard
vcard: "http://www.w3.org/2006/vcard/ns#",
// ChatMessage
litepub: "http://litepub.social/ns#",
ChatMessage: "litepub:ChatMessage",
directMessage: "litepub:directMessage",
},
],
},
x,
);
return Object.assign({}, WellKnownContext, x);
};
export const attachLdSignature = async (

View file

@ -215,7 +215,7 @@
@click.stop="react()"
>
<i :class="icon('ph-smiley')"></i>
<p class="count" v-if="reactionCount > 0 && hideEmojiViewer">{{reactionCount}}</p>
<p v-if="reactionCount > 0 && hideEmojiViewer" class="count">{{reactionCount}}</p>
</button>
<button
v-if="
@ -228,7 +228,7 @@
@click.stop="undoReact(appearNote)"
>
<i :class="icon('ph-minus')"></i>
<p class="count" v-if="reactionCount > 0 && hideEmojiViewer">{{reactionCount}}</p>
<p v-if="reactionCount > 0 && hideEmojiViewer" class="count">{{reactionCount}}</p>
</button>
<XQuoteButton class="button" :note="appearNote" />
<button

View file

@ -81,8 +81,8 @@
</MkTab>
<MkPagination
ref="repliesPagingComponent"
v-if="tab === 'replies' && note.repliesCount > 0"
ref="repliesPagingComponent"
v-slot="{ items }"
:pagination="repliesPagination"
>

View file

@ -107,7 +107,7 @@
@click.stop="react()"
>
<i :class="icon('ph-smiley')"></i>
<p class="count" v-if="reactionCount > 0 && hideEmojiViewer">{{reactionCount}}</p>
<p v-if="reactionCount > 0 && hideEmojiViewer" class="count">{{reactionCount}}</p>
</button>
<button
v-if="
@ -120,7 +120,7 @@
@click.stop="undoReact(appearNote)"
>
<i :class="icon('ph-minus')"></i>
<p class="count" v-if="reactionCount > 0 && hideEmojiViewer">{{reactionCount}}</p>
<p v-if="reactionCount > 0 && hideEmojiViewer" class="count">{{reactionCount}}</p>
</button>
<XQuoteButton class="button" :note="appearNote" />
<button

View file

@ -75,6 +75,7 @@
import { computed, onMounted, onUnmounted, ref } from "vue";
import type { Connection } from "firefish-js/src/streaming";
import type { Channels } from "firefish-js/src/streaming.types";
import type { entities } from "firefish-js";
import XReactionIcon from "@/components/MkReactionIcon.vue";
import XReactionTooltip from "@/components/MkReactionTooltip.vue";
import { i18n } from "@/i18n";
@ -89,7 +90,6 @@ import type {
ReactionNotificationFolded,
} from "@/types/notification";
import XNote from "@/components/MkNote.vue";
import type { entities } from "firefish-js";
const props = withDefaults(
defineProps<{

View file

@ -17,8 +17,8 @@
<template #default="{ foldedItems: notifications }">
<XList
:items="notifications"
v-slot="{ item: notification }"
:items="notifications"
class="elsfgstc"
:no-gap="true"
>

View file

@ -38,7 +38,7 @@
</MkButton>
<MkLoading v-else class="loading" />
</div>
<slot :items="items" :foldedItems="foldedItems"></slot>
<slot :items="items" :folded-items="foldedItems"></slot>
<div
v-show="!pagination.reversed && more"
key="_more_"
@ -105,9 +105,9 @@ export type MkPaginationType<
updateItem: (id: string, replacer: (old: Item) => Item) => boolean;
};
export type PagingAble = {
export interface PagingAble {
id: string;
};
}
export type PagingKeyOf<T> = TypeUtils.EndpointsOf<T[]>;
// biome-ignore lint/suspicious/noExplicitAny: Used Intentionally

View file

@ -15,12 +15,12 @@
<script lang="ts" setup>
import { shallowRef } from "vue";
import QRCodeVue3 from "qrcode-vue3";
import MkModal from "@/components/MkModal.vue";
import MkButton from "@/components/MkButton.vue";
import { i18n } from "@/i18n";
import QRCodeVue3 from "qrcode-vue3";
const props = defineProps<{
defineProps<{
qrCode: string;
}>();

View file

@ -1,7 +1,7 @@
<template>
<button
ref="el"
v-if="canRenote && defaultStore.state.seperateRenoteQuote"
ref="el"
v-tooltip.noDelay.bottom="i18n.ts.quote"
class="eddddedb _button"
@click.stop="quote()"

View file

@ -25,8 +25,8 @@
</div>
<MkPagination
ref="pagingComponent"
:pagination="pagination"
v-slot="{ items }"
:pagination="pagination"
>
<MkUserCardMini v-for="{ user: user } in items" :key="user.id" :user="user" />
</MkPagination>

View file

@ -382,7 +382,7 @@ function focusFooter(ev) {
> .body {
min-height: 2em;
max-height: 5em;
filter: blur(4px);
filter: blur(5px);
:deep(span) {
animation: none !important;
transform: none !important;

View file

@ -1,8 +1,8 @@
import type { entities } from "firefish-js";
import type {
FoldableNotification,
NotificationFolded,
} from "@/types/notification";
import type { entities } from "firefish-js";
interface FoldOption {
/** If items length is 1, skip aggregation */

View file

@ -4,7 +4,7 @@ export type FoldableNotification =
| entities.RenoteNotification
| entities.ReactionNotification;
type Fold<T extends FoldableNotification> = {
interface Fold<T extends FoldableNotification> {
id: string;
type: T["type"];
createdAt: T["createdAt"];
@ -13,7 +13,7 @@ type Fold<T extends FoldableNotification> = {
userIds: entities.User["id"][];
users: entities.User[];
notifications: T[];
};
}
export type RenoteNotificationFolded = Fold<entities.RenoteNotification>;