mirror of
https://git.joinfirefish.org/firefish/firefish.git
synced 2024-05-18 20:11:10 +02:00
Merge branch 'develop' into refactor/push-notification
This commit is contained in:
commit
c13d6344e1
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2067,3 +2067,4 @@ useThisAccountConfirm: このアカウントで操作を続けますか?
|
|||
getQrCode: QRコードを表示
|
||||
copyRemoteFollowUrl: リモートからフォローするURLをコピー
|
||||
foldNotification: 同じ種類の通知をまとめて表示する
|
||||
slashQuote: 繋げて引用
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "firefish",
|
||||
"version": "20240424",
|
||||
"version": "20240430",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://firefish.dev/firefish/firefish.git"
|
||||
|
|
|
@ -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})`;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}`);
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -81,8 +81,8 @@
|
|||
</MkTab>
|
||||
|
||||
<MkPagination
|
||||
ref="repliesPagingComponent"
|
||||
v-if="tab === 'replies' && note.repliesCount > 0"
|
||||
ref="repliesPagingComponent"
|
||||
v-slot="{ items }"
|
||||
:pagination="repliesPagination"
|
||||
>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<{
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
<template #default="{ foldedItems: notifications }">
|
||||
<XList
|
||||
:items="notifications"
|
||||
v-slot="{ item: notification }"
|
||||
:items="notifications"
|
||||
class="elsfgstc"
|
||||
:no-gap="true"
|
||||
>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}>();
|
||||
|
||||
|
|
|
@ -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()"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
Loading…
Reference in a new issue