Merge upstream

This commit is contained in:
ASTRO:? 2025-05-16 08:00:55 +09:00
commit b80629abed
No known key found for this signature in database
75 changed files with 2749 additions and 3298 deletions

View file

@ -23,13 +23,7 @@ services:
environment:
DFLY_snapshot_cron: '* * * * *'
DFLY_version_check: false
DFLY_tcp_backlog: 2048
DFLY_default_lua_flags: allow-undeclared-keys
DFLY_pipeline_squash: 0
DFLY_multi_exec_squash: false
DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4
networks:
- internal_network
volumes:
@ -37,7 +31,7 @@ services:
db:
restart: unless-stopped
image: postgres:15-alpine
image: postgres:17-alpine
networks:
- internal_network
environment:

1
.github/CODEOWNERS vendored
View file

@ -1 +0,0 @@
* @SWREI

4
.github/FUNDING.yml vendored
View file

@ -1,4 +0,0 @@
# These are supported funding model platforms
github: [misskey-dev]
patreon: syuilo

View file

@ -1,97 +0,0 @@
name: 🐛 Bug Report
description: Create a report to help us improve
labels: ["⚠bug?"]
body:
- type: markdown
attributes:
value: |
Thanks for reporting!
First, in order to avoid duplicate Issues, please search to see if the problem you found has already been reported.
Also, If you are NOT owner/admin of server, PLEASE DONT REPORT SERVER SPECIFIC ISSUES TO HERE! (e.g. feature XXX is not working in misskey.example) Please try with another misskey servers, and if your issue is only reproducible with specific server, contact your server's owner/admin first.
- type: textarea
attributes:
label: 💡 Summary
description: Tell us what the bug is
validations:
required: true
- type: textarea
attributes:
label: 🥰 Expected Behavior
description: Tell us what should happen
validations:
required: true
- type: textarea
attributes:
label: 🤬 Actual Behavior
description: |
Tell us what happens instead of the expected behavior.
Please include errors from the developer console and/or server log files if you have access to them.
validations:
required: true
- type: textarea
attributes:
label: 📝 Steps to Reproduce
placeholder: |
1.
2.
3.
validations:
required: false
- type: textarea
attributes:
label: 💻 Frontend Environment
description: |
Tell us where on the platform it happens
DO NOT WRITE "latest". Please provide the specific version.
Examples:
* Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4
* Browser: Chrome 113.0.5672.126
* Server URL: misskey.io
* Misskey: 13.x.x
value: |
* Model and OS of the device(s):
* Browser:
* Server URL:
* Misskey:
render: markdown
validations:
required: false
- type: textarea
attributes:
label: 🛰 Backend Environment (for server admin)
description: |
Tell us where on the platform it happens
DO NOT WRITE "latest". Please provide the specific version.
If you are using a managed service, put that after the version.
Examples:
* Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment
* Misskey: 13.x.x
* Node: 22.x.x
* PostgreSQL: 15.x.x
* Redis: 7.x.x
* OS and Architecture: Ubuntu 22.04.2 LTS aarch64
value: |
* Installation Method or Hosting Service:
* Misskey:
* Node:
* PostgreSQL:
* Redis:
* OS and Architecture:
render: markdown
validations:
required: false
- type: checkboxes
attributes:
label: Do you want to address this bug yourself?
options:
- label: Yes, I will patch the bug myself and send a pull request

View file

@ -1,22 +0,0 @@
name: ✨ Feature Request
description: Suggest an idea for this project
labels: ["✨Feature"]
body:
- type: textarea
attributes:
label: Summary
description: Tell us what the suggestion is
validations:
required: true
- type: textarea
attributes:
label: Purpose
description: Describe the specific problem or need you think this feature will solve, and who it will help.
validations:
required: true
- type: checkboxes
attributes:
label: Do you want to implement this feature yourself?
options:
- label: Yes, I will implement this by myself and send a pull request

View file

@ -1,4 +0,0 @@
contact_links:
- name: 💬 Misskey official Discord
url: https://discord.gg/Wp8gVStHW3
about: Chat freely about Misskey

View file

@ -1,23 +0,0 @@
<!-- お読みください / README
PRありがとうございます PRを作成する前に、コントリビューションガイドをご確認ください:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
## What
<!-- このPRで何をしたのか どう変わるのか? -->
<!-- What did you do with this PR? How will it change things? -->
## Why
<!-- なぜそうするのか? どういう意図なのか? 何が困っているのか? -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
## Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->
## Checklist
- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md)
- [ ] Test working in a local environment
- [ ] (If needed) Update CHANGELOG.md
- [ ] (If possible) Add tests

View file

@ -1,23 +0,0 @@
<!-- お読みください / README
PRありがとうございます PRを作成する前に、コントリビューションガイドをご確認ください:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
## What
<!-- このPRで何をしたのか どう変わるのか? -->
<!-- What did you do with this PR? How will it change things? -->
## Why
<!-- なぜそうするのか? どういう意図なのか? 何が困っているのか? -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
## Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->
## Checklist
- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md)
- [ ] Test working in a local environment
- [ ] (If needed) Update CHANGELOG.md
- [ ] (If possible) Add tests

View file

@ -1,20 +0,0 @@
## Summary
This is a release PR.
For more information on the release instructions, please see:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md#release
## For reviewers
- CHANGELOGに抜け漏れは無いか
- バージョンの上げ方は適切か
- 他にこのリリースに含めなければならない変更は無いか
- 全体的な変更内容を俯瞰し問題は無いか
- レビューされていないコミットがある場合は、それが問題ないか
- 最終的な動作確認を行い問題は無いか
などを確認し、リリースする準備が整っていると思われる場合は approve してください。
## Checklist
- [ ] package.jsonのバージョンが正しく更新されている
- [ ] CHANGELOGが過不足無く更新されている
- [ ] CIが全て通っている

View file

@ -1,20 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 100
# Add only the root, not each workspace item
# https://github.com/dependabot/dependabot-core/issues/4993#issuecomment-1289133027
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 0

34
.github/labeler.yml vendored
View file

@ -1,34 +0,0 @@
'packages/backend':
- any:
- changed-files:
- any-glob-to-any-file: ['packages/backend/**/*']
'packages/backend:test':
- any:
- changed-files:
- any-glob-to-any-file: ['packages/backend/test/**/*']
'packages/frontend':
- any:
- changed-files:
- any-glob-to-any-file: ['packages/frontend/**/*']
'packages/frontend:test':
- any:
- changed-files:
- any-glob-to-any-file: ['cypress/**/*']
'packages/sw':
- any:
- changed-files:
- any-glob-to-any-file: ['packages/sw/**/*']
'packages/misskey-js':
- any:
- changed-files:
- any-glob-to-any-file: ['packages/misskey-js/**/*']
'packages/misskey-js:test':
- any:
- changed-files:
- any-glob-to-any-file: ['packages/misskey-js/test/**/*', 'packages/misskey-js/test-d/**/*']

View file

@ -1,15 +0,0 @@
url: 'http://misskey.local'
# ローカルでテストするときにポートを被らないようにするためデフォルトのものとは変える(以下同じ)
port: 61812
db:
host: 127.0.0.1
port: 54312
db: test-misskey
user: postgres
pass: ''
redis:
host: 127.0.0.1
port: 56312
id: aidx

View file

@ -1,24 +0,0 @@
<!-- お読みください / README
PRありがとうございます PRを作成する前に、コントリビューションガイドをご確認ください:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
## What
<!-- このPRで何をしたのか どう変わるのか? -->
<!-- What did you do with this PR? How will it change things? -->
## Why
<!-- なぜそうするのか? どういう意図なのか? 何が困っているのか? -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
## Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->
## Checklist
- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md)
- [ ] Test working in a local environment
- [ ] (If needed) Add story of storybook
- [ ] (If needed) Update CHANGELOG.md
- [ ] (If possible) Add tests

View file

@ -1,136 +0,0 @@
name: Test (backend)
on:
push:
branches:
- oscar
paths:
- packages/backend/**
# for permissions
- packages/misskey-js/**
pull_request:
paths:
- packages/backend/**
# for permissions
- packages/misskey-js/**
jobs:
unit:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
dragonfly:
image: docker.dragonflydb.io/dragonflydb/dragonfly
options: --ulimit "memlock=-1"
env:
DFLY_version_check: false
DFLY_tcp_backlog: 2048
DFLY_default_lua_flags: allow-undeclared-keys
DFLY_pipeline_squash: 0
DFLY_multi_exec_squash: false
DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Install FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.3.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter backend test-and-coverage
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json
e2e:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
dragonfly:
image: docker.dragonflydb.io/dragonflydb/dragonfly
options: --ulimit "memlock=-1"
env:
DFLY_version_check: false
DFLY_tcp_backlog: 2048
DFLY_default_lua_flags: allow-undeclared-keys
DFLY_pipeline_squash: 0
DFLY_multi_exec_squash: false
DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.3.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter backend test-and-coverage:e2e
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json

View file

@ -1,48 +0,0 @@
name: API report (misskey.js)
on:
push:
paths:
- packages/misskey-js/**
pull_request:
paths:
- packages/misskey-js/**
jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v4.3.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Install dependencies
run: pnpm i --frozen-lockfile
- name: Build
run: pnpm --filter misskey-js build
- name: Check files
run: ls packages/misskey-js/built
- name: API report
run: pnpm --filter misskey-js api-prod
- name: Show report
if: always()
run: cat packages/misskey-js/temp/misskey-js.api.md

View file

@ -1,31 +0,0 @@
name: Check Misskey JS version
on:
push:
branches:
- oscar
paths:
- packages/misskey-js/package.json
- package.json
pull_request:
paths:
- packages/misskey-js/package.json
- package.json
jobs:
check-version:
# ルートの package.json と packages/misskey-js/package.json のバージョンが一致しているかを確認する
name: Check version
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Check version
run: |
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
echo "Version mismatch!"
exit 1
fi

View file

View file

@ -1,54 +0,0 @@
name: Publish Docker Image
on:
push:
branches:
- oscar
tags:
- '**-oscar.*'
workflow_dispatch:
jobs:
push_to_registry:
name: Push Docker image to GitHub Container Registry
runs-on: ubuntu-22.04
if: github.repository == 'oscar-surf/misskey'
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/oscar-surf/misskey
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare image tags
run: |
echo "FORMATTED_BRANCH_NAME=$(echo ${{ github.ref_name }} | sed -e 's/\//-/g' )" >> $GITHUB_ENV
- name: Build and Push to GitHub Container Registry
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
labels: ${{ env.FORMATTED_BRANCH_NAME }}
cache-from: type=registry,ref=ghcr.io/oscar-surf/misskey:oscar-buildcache
cache-to: type=registry,ref=ghcr.io/oscar-surf/misskey:oscar-buildcache,mode=max
tags: |
ghcr.io/oscar-surf/misskey:latest
ghcr.io/oscar-surf/misskey:${{ env.FORMATTED_BRANCH_NAME }}

View file

@ -1,36 +0,0 @@
name: Dockle
on:
push:
branches:
- oscar
pull_request:
jobs:
dockle:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Build an image from Dockerfile
uses: docker/build-push-action@v6
with:
context: .
push: false
provenance: false
cache-from: type=registry,ref=ghcr.io/oscar-surf/misskey:oscar-buildcache
tags: |
misskey:scan
- name: Run dockle
uses: docker://goodwithtech/dockle:v0.4.14
env:
DOCKLE_OUTPUT_FORMAT: list
DOCKLE_EXIT_CODE: 1
DOCKLE_EXIT_LEVEL: WARN
DOCKLE_IGNORES: CIS-DI-0005,CIS-DI-0010
DOCKLE_DEBUG: true
with:
args: 'misskey:scan'

View file

@ -1,90 +0,0 @@
name: Lint
on:
push:
branches:
- oscar
paths:
- packages/backend/**
- packages/frontend/**
- packages/sw/**
- packages/misskey-js/**
- packages/shared/.eslintrc.js
pull_request:
paths:
- packages/backend/**
- packages/frontend/**
- packages/sw/**
- packages/misskey-js/**
- packages/shared/.eslintrc.js
jobs:
pnpm_install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4.3.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
lint:
needs: [pnpm_install]
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
workspace:
- backend
- frontend
- sw
- misskey-js
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4.3.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- run: pnpm --filter ${{ matrix.workspace }} run eslint
typecheck:
needs: [pnpm_install]
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
workspace:
- backend
- misskey-js
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4.3.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- run: pnpm -r run build:tsc
if: ${{ matrix.workspace == 'backend' }}
- run: pnpm --filter misskey-js run build
if: ${{ matrix.workspace == 'backend' }}
- run: pnpm --filter ${{ matrix.workspace }} run typecheck

View file

@ -1,57 +0,0 @@
name: Test (frontend)
on:
push:
branches:
- oscar
paths:
- packages/frontend/**
# for permissions
- packages/misskey-js/**
# for e2e
- packages/backend/**
pull_request:
paths:
- packages/frontend/**
# for permissions
- packages/misskey-js/**
# for e2e
- packages/backend/**
jobs:
vitest:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.3.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter frontend test-and-coverage
- name: Upload Coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/frontend/coverage/coverage-final.json

View file

@ -1,62 +0,0 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Test (misskey.js)
on:
push:
branches:
- oscar
paths:
- packages/misskey-js/**
pull_request:
paths:
- packages/misskey-js/**
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.3.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Build
run: pnpm --filter misskey-js build
- name: Test
run: pnpm --filter misskey-js test
env:
CI: true
- name: Upload Coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/misskey-js/coverage/coverage-final.json

View file

@ -1,40 +0,0 @@
name: Test (production install and build)
on:
push:
branches:
- oscar
pull_request:
env:
NODE_ENV: production
jobs:
production:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.3.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config/default.yml
- name: Build
run: pnpm build

View file

@ -1,45 +0,0 @@
name: Test (backend)
on:
push:
branches:
- oscar
paths:
- packages/backend/**
pull_request:
paths:
- packages/backend/**
jobs:
validate-api-json:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.3.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install Redocly CLI
run: npm i -g @redocly/cli
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .config/example.yml .config/default.yml
- name: Build and generate
run: pnpm build && pnpm --filter backend generate-api-json
- name: Validation
run: npx @redocly/cli lint --extends=minimal ./packages/backend/built/api.json

View file

@ -46,7 +46,7 @@ RUN apt-get update \
WORKDIR /misskey
COPY --link pnpm-lock.yaml ./
RUN npm install -g pnpm@10
RUN npm install -g pnpm@10 && mkdir -p /root/.local/share/pnpm/.tools
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm fetch --ignore-scripts
@ -81,6 +81,7 @@ WORKDIR /misskey
COPY --chown=misskey:misskey pnpm-lock.yaml ./
RUN npm install -g pnpm@10
COPY --chown=misskey:misskey --from=target-builder /root/.local/share/pnpm/.tools ./.local/share/pnpm/.tools
COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules

View file

@ -27,7 +27,7 @@ spec:
ports:
- containerPort: 3000
- name: postgres
image: postgres:15-alpine
image: postgres:17-alpine
env:
- name: POSTGRES_USER
value: "example-misskey-user"
@ -42,20 +42,8 @@ spec:
env:
- name: DFLY_version_check
value: false
- name: DFLY_tcp_backlog
value: 2048
- name: DFLY_default_lua_flags
value: allow-undeclared-keys
- name: DFLY_pipeline_squash
value: 0
- name: DFLY_multi_exec_squash
value: false
- name: DFLY_conn_io_threads
value: 4
- name: DFLY_epoll_file_threads
value: 4
- name: DFLY_proactor_threads
value: 4
ports:
- containerPort: 6379
volumes:

View file

@ -11,13 +11,7 @@ services:
environment:
DFLY_snapshot_cron: '* * * * *'
DFLY_version_check: false
DFLY_tcp_backlog: 2048
DFLY_default_lua_flags: allow-undeclared-keys
DFLY_pipeline_squash: 0
DFLY_multi_exec_squash: false
DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4
ports:
- "6379:6379"
volumes:
@ -25,7 +19,7 @@ services:
db:
restart: always
image: postgres:15-alpine
image: postgres:17-alpine
ports:
- "5432:5432"
env_file:

View file

@ -31,13 +31,7 @@ services:
environment:
DFLY_snapshot_cron: '* * * * *'
DFLY_version_check: false
DFLY_tcp_backlog: 2048
DFLY_default_lua_flags: allow-undeclared-keys
DFLY_pipeline_squash: 0
DFLY_multi_exec_squash: false
DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4
networks:
- internal_network
volumes:
@ -45,7 +39,7 @@ services:
db:
restart: always
image: postgres:15-alpine
image: postgres:17-alpine
networks:
- internal_network
env_file:

View file

@ -1,12 +1,12 @@
{
"name": "misskey",
"version": "2024.5.0-oscar.24b",
"version": "2024.5.0-oscar.25",
"codename": "nasubi",
"repository": {
"type": "git",
"url": "https://git.psec.dev/oscar-surf/misskey.git"
},
"packageManager": "pnpm@10.7.0",
"packageManager": "pnpm@10.11.0",
"workspaces": [
"packages/frontend",
"packages/backend",
@ -22,9 +22,9 @@
"build": "pnpm build-pre && pnpm -r build && pnpm build-assets",
"build-storybook": "pnpm --filter frontend build-storybook",
"build-misskey-js-with-types": "pnpm build-pre && pnpm -r build:tsc && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
"start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js",
"start:docker": "pnpm check:connect && cd packages/backend && exec node ./built/boot/entry.js",
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
"start": "pnpm check:connect && cd packages/backend && cross-env-shell \"node $MK_NODE_ARGS ./built/boot/entry.js\"",
"start:docker": "pnpm check:connect && cd packages/backend && exec cross-env-shell \"node $MK_NODE_ARGS ./built/boot/entry.js\"",
"start:test": "cd packages/backend && cross-env NODE_ENV=test cross-env-shell \"node $MK_NODE_ARGS ./built/boot/entry.js\"",
"init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate",
"revert": "cd packages/backend && pnpm revert",
@ -47,39 +47,47 @@
},
"resolutions": {
"@aiscript-dev/aiscript-languageserver": "github:aiscript-dev/aiscript-languageserver#0.1.6",
"@misskey-dev/summaly": "github:MisskeyIO/summaly#5.2.1-io.1",
"@tensorflow/tfjs": "4.22.0",
"@tensorflow/tfjs-core": "4.22.0",
"axios": "1.8.4",
"@tensorflow/tfjs-node": "4.22.0",
"@types/punycode": "2.1.4",
"@types/punycode.js": "npm:@types/punycode@2.1.4",
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.16",
"axios": "1.9.0",
"chokidar": "4.0.3",
"cookie": "1.0.2",
"cookie-signature": "1.2.2",
"debug": "4.4.0",
"esbuild": "0.25.2",
"esbuild": "0.25.4",
"jpeg-js": "0.4.4",
"lodash": "4.17.21",
"sharp": "0.33.5",
"sharp": "0.34.0-rc.0",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"tough-cookie": "5.1.2",
"webgl-audiovisualizer": "github:tar-bin/webgl-audiovisualizer",
"web-streams-polyfill": "4.1.0"
},
"dependencies": {
"cssnano": "7.0.6",
"execa": "9.5.2",
"cssnano": "7.0.7",
"execa": "9.5.3",
"js-yaml": "4.1.0",
"postcss": "8.5.3",
"terser": "5.39.0",
"typescript": "5.8.2"
"terser": "5.39.1",
"typescript": "5.8.3"
},
"devDependencies": {
"@types/node": "22.13.14",
"@types/node": "22.15.17",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"cross-env": "7.0.3",
"cypress": "14.2.1",
"cypress": "14.3.3",
"eslint": "8.57.1",
"ncp": "2.0.0",
"start-server-and-test": "2.0.11"
},
"optionalDependencies": {
"@tensorflow/tfjs-core": "4.22.0"
"@tensorflow/tfjs-core": "managed"
},
"pnpm": {
"neverBuiltDependencies": []

View file

@ -0,0 +1,11 @@
export class SSOWantEmailAddressNormalized1745247339195 {
name = 'SSOWantEmailAddressNormalized1745247339195'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "sso_service_provider" ADD "wantEmailAddressNormalized" boolean NOT NULL DEFAULT true`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "sso_service_provider" DROP COLUMN "wantEmailAddressNormalized"`);
}
}

View file

@ -33,18 +33,18 @@
"generate-api-json": "pnpm build && node ./scripts/generate_api_json.js"
},
"optionalDependencies": {
"@swc/core-darwin-arm64": "1.11.13",
"@swc/core-darwin-x64": "1.11.13",
"@swc/core-linux-arm-gnueabihf": "1.11.13",
"@swc/core-linux-arm64-gnu": "1.11.13",
"@swc/core-linux-arm64-musl": "1.11.13",
"@swc/core-linux-x64-gnu": "1.11.13",
"@swc/core-linux-x64-musl": "1.11.13",
"@swc/core-win32-arm64-msvc": "1.11.13",
"@swc/core-win32-ia32-msvc": "1.11.13",
"@swc/core-win32-x64-msvc": "1.11.13",
"@tensorflow/tfjs": "4.22.0",
"@tensorflow/tfjs-node": "4.22.0",
"@swc/core-darwin-arm64": "1.11.24",
"@swc/core-darwin-x64": "1.11.24",
"@swc/core-linux-arm-gnueabihf": "1.11.24",
"@swc/core-linux-arm64-gnu": "1.11.24",
"@swc/core-linux-arm64-musl": "1.11.24",
"@swc/core-linux-x64-gnu": "1.11.24",
"@swc/core-linux-x64-musl": "1.11.24",
"@swc/core-win32-arm64-msvc": "1.11.24",
"@swc/core-win32-ia32-msvc": "1.11.24",
"@swc/core-win32-x64-msvc": "1.11.24",
"@tensorflow/tfjs": "managed",
"@tensorflow/tfjs-node": "managed",
"bufferutil": "4.0.9",
"slacc-android-arm-eabi": "0.0.10",
"slacc-android-arm64": "0.0.10",
@ -63,11 +63,11 @@
},
"dependencies": {
"@authenio/samlify-node-xmllint": "2.0.0",
"@aws-sdk/client-s3": "3.779.0",
"@aws-sdk/lib-storage": "3.779.0",
"@bull-board/api": "6.7.10",
"@bull-board/fastify": "6.7.10",
"@bull-board/ui": "6.7.10",
"@aws-sdk/client-s3": "3.808.0",
"@aws-sdk/lib-storage": "3.808.0",
"@bull-board/api": "6.9.6",
"@bull-board/fastify": "6.9.6",
"@bull-board/ui": "6.9.6",
"@discordapp/twemoji": "15.1.0",
"@elastic/elasticsearch": "8.17.1",
"@fastify/accepts": "5.0.2",
@ -78,20 +78,20 @@
"@fastify/http-proxy": "11.1.2",
"@fastify/multipart": "9.0.3",
"@fastify/static": "8.1.1",
"@fastify/view": "11.0.0",
"@misskey-dev/sharp-read-bmp": "1.2.0",
"@misskey-dev/summaly": "github:MisskeyIO/summaly#5.1.3",
"@napi-rs/canvas": "0.1.68",
"@nestjs/common": "11.0.12",
"@nestjs/core": "11.0.12",
"@nestjs/testing": "11.0.12",
"@fastify/view": "11.1.0",
"@misskey-dev/sharp-read-bmp": "1.3.0",
"@misskey-dev/summaly": "managed",
"@napi-rs/canvas": "0.1.70",
"@nestjs/common": "11.1.0",
"@nestjs/core": "11.1.0",
"@nestjs/testing": "11.1.0",
"@peertube/http-signature": "1.7.0",
"@simplewebauthn/server": "13.1.1",
"@sinonjs/fake-timers": "11.3.1",
"@smithy/node-http-handler": "4.0.4",
"@swc/cli": "0.6.0",
"@swc/core": "1.11.13",
"@twemoji/parser": "15.1.1",
"@swc/cli": "0.7.7",
"@swc/core": "1.11.24",
"@twemoji/parser": "16.0.0",
"accepts": "1.3.8",
"ajv": "8.17.1",
"archiver": "7.0.1",
@ -99,39 +99,39 @@
"bcryptjs": "3.0.2",
"blurhash": "2.0.5",
"body-parser": "2.2.0",
"bullmq": "5.45.2",
"bullmq": "5.52.2",
"cacheable-lookup": "7.0.0",
"cbor": "10.0.3",
"chalk": "5.4.1",
"chalk-template": "1.1.0",
"chokidar": "4.0.3",
"chokidar": "managed",
"cli-highlight": "2.1.11",
"color-convert": "3.0.1",
"color-convert": "3.1.0",
"content-disposition": "0.5.4",
"date-fns": "4.1.0",
"deep-email-validator": "0.1.21",
"fastify": "5.2.2",
"fastify": "5.3.3",
"fastify-http-errors-enhanced": "6.0.1",
"fastify-raw-body": "5.0.0",
"feed": "4.2.2",
"file-type": "20.4.1",
"feed": "5.0.1",
"file-type": "20.5.0",
"fluent-ffmpeg": "2.1.3",
"form-data": "4.0.2",
"got": "14.4.7",
"hpagent": "1.2.0",
"htmlescape": "1.1.1",
"http-link-header": "1.1.3",
"ioredis": "5.6.0",
"ioredis": "5.6.1",
"ip-cidr": "4.0.2",
"ipaddr.js": "2.2.0",
"is-svg": "5.1.0",
"jose": "6.0.10",
"is-svg": "6.0.0",
"jose": "6.0.11",
"js-yaml": "4.1.0",
"jsdom": "26.0.0",
"jsdom": "26.1.0",
"json5": "2.2.3",
"jsonld": "8.3.3",
"jsrsasign": "11.1.0",
"meilisearch": "0.49.0",
"meilisearch": "0.50.0",
"mfm-js": "0.24.0",
"microformats-parser": "2.0.2",
"mime-types": "3.0.1",
@ -142,15 +142,15 @@
"nested-property": "4.0.0",
"node-fetch": "3.3.2",
"node-forge": "1.3.1",
"nodemailer": "6.10.0",
"nodemailer": "7.0.3",
"nsfwjs": "4.2.0",
"oauth": "0.10.2",
"oauth2orize": "1.12.0",
"oauth2orize-pkce": "0.1.2",
"os-utils": "0.0.14",
"otpauth": "9.4.0",
"parse5": "7.2.1",
"pg": "8.14.1",
"parse5": "7.3.0",
"pg": "8.16.0",
"pino": "9.6.0",
"pino-pretty": "13.0.0",
"pkce-challenge": "5.0.0",
@ -162,37 +162,37 @@
"qrcode": "1.5.4",
"random-seed": "0.3.0",
"ratelimiter": "3.4.1",
"re2": "1.21.4",
"re2": "1.21.5",
"reflect-metadata": "0.2.2",
"rename": "1.0.4",
"rss-parser": "3.13.0",
"rxjs": "7.8.2",
"samlify": "2.9.1",
"sanitize-html": "2.15.0",
"samlify": "2.10.0",
"sanitize-html": "2.16.0",
"secure-json-parse": "4.0.0",
"sharp": "0.33.5",
"sharp": "managed",
"slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
"systeminformation": "5.25.11",
"tinycolor2": "1.6.0",
"tmp": "0.2.3",
"tsc-alias": "1.8.13",
"tsc-alias": "1.8.16",
"tsconfig-paths": "4.2.0",
"typeorm": "0.3.21",
"typescript": "5.8.2",
"typeorm": "0.3.23",
"typescript": "5.8.3",
"ulid": "3.0.0",
"vary": "1.1.2",
"web-push": "3.6.7",
"ws": "8.18.1",
"ws": "8.18.2",
"xev": "3.0.2",
"xmlbuilder": "15.1.1"
},
"devDependencies": {
"@jest/globals": "29.7.0",
"@misskey-dev/eslint-plugin": "1.0.0",
"@nestjs/platform-express": "11.0.12",
"@swc/jest": "0.2.37",
"@nestjs/platform-express": "11.1.0",
"@swc/jest": "0.2.38",
"@types/accepts": "1.3.7",
"@types/archiver": "6.0.3",
"@types/body-parser": "1.19.5",
@ -208,21 +208,21 @@
"@types/jsrsasign": "10.5.15",
"@types/mime-types": "2.1.4",
"@types/ms": "2.1.0",
"@types/node": "22.13.14",
"@types/node": "22.15.17",
"@types/node-forge": "1.3.11",
"@types/nodemailer": "6.4.17",
"@types/oauth": "0.9.6",
"@types/oauth2orize": "1.11.5",
"@types/oauth2orize-pkce": "0.1.2",
"@types/pg": "8.11.11",
"@types/pg": "8.15.1",
"@types/psl": "1.1.3",
"@types/pug": "2.0.10",
"@types/punycode.js": "npm:@types/punycode@2.1.4",
"@types/punycode.js": "managed",
"@types/qrcode": "1.5.5",
"@types/random-seed": "0.3.5",
"@types/ratelimiter": "3.4.6",
"@types/rename": "1.0.7",
"@types/sanitize-html": "2.15.0",
"@types/sanitize-html": "2.16.0",
"@types/semver": "7.7.0",
"@types/simple-oauth2": "5.0.7",
"@types/sinonjs__fake-timers": "8.1.5",
@ -230,18 +230,18 @@
"@types/tmp": "0.2.6",
"@types/vary": "1.1.3",
"@types/web-push": "3.6.4",
"@types/ws": "8.18.0",
"@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"aws-sdk-client-mock": "4.1.0",
"cross-env": "7.0.3",
"eslint": "8.57.1",
"eslint-plugin-import": "2.31.0",
"execa": "9.5.2",
"execa": "9.5.3",
"fkill": "9.0.0",
"jest": "29.7.0",
"jest-mock": "29.7.0",
"nodemon": "3.1.9",
"nodemon": "3.1.10",
"pid-port": "1.0.2",
"simple-oauth2": "5.1.0"
}

View file

@ -127,6 +127,8 @@ type Source = {
perUserNotificationsMaxCount?: number;
deactivateAntennaThreshold?: number;
pidFile: string;
extraHead?: string;
};
export type Config = {
@ -232,6 +234,7 @@ export type Config = {
perUserNotificationsMaxCount: number;
deactivateAntennaThreshold: number;
pidFile: string;
extraHead: string | undefined;
};
const _filename = fileURLToPath(import.meta.url);
@ -341,6 +344,7 @@ export function loadConfig(): Config {
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
deactivateAntennaThreshold: config.deactivateAntennaThreshold ?? (1000 * 60 * 60 * 24 * 7),
pidFile: config.pidFile,
extraHead: config.extraHead,
};
}

View file

@ -99,7 +99,7 @@ export class SearchService {
if (config.meilisearch?.scope) {
this.meilisearchIndexScope = config.meilisearch.scope;
}
/*this.meilisearchNoteIndex.updateSettings({
this.meilisearchNoteIndex.updateSettings({
searchableAttributes: [
'text',
'cw',
@ -120,11 +120,10 @@ export class SearchService {
pagination: {
maxTotalHits: 10000,
},
});*/
});
} else if (this.elasticsearch) {
this.elasticsearchNoteIndex = `${config.elasticsearch!.index}`;
this.elasticsearchIdField = `${config.host}_id`;
/* index
this.elasticsearch.indices.exists({
index: this.elasticsearchNoteIndex,
}).then((indexExists: boolean) => {
@ -178,7 +177,6 @@ export class SearchService {
}).catch((error: any) => {
this.logger.error('Error while checking if index exists', error);
});
*/
}
}
@ -217,7 +215,6 @@ export class SearchService {
primaryKey: 'id',
});
} else if (this.elasticsearch) {
/* index
const body = {
createdAt: createdAt.getTime(),
userId: note.userId,
@ -234,7 +231,6 @@ export class SearchService {
}).catch((error: any) => {
this.logger.error(error);
});
*/
}
}
@ -245,14 +241,12 @@ export class SearchService {
if (this.meilisearch) {
await this.meilisearchNoteIndex?.deleteDocument(note.id);
} else if (this.elasticsearch) {
/* index
await this.elasticsearch.delete({
index: `${this.elasticsearchNoteIndex}-${this.idService.parse(note.id).date.toISOString().slice(0, 7).replace(/-/g, '')}`,
id: note.id,
}).catch((error) => {
this.logger.error(error);
});
*/
}
}
@ -266,7 +260,7 @@ export class SearchService {
query: {
match_all: {},
},
}).catch((error) => {
}).catch((error: any) => {
this.logger.error(error);
});
}
@ -383,7 +377,7 @@ export class SearchService {
const noteIds = res.hits.hits.map((hit) => {
const source = hit._source as Record<string, unknown>;
return (source[this.elasticsearchIdField] as string) || null;
}).filter((id): id is string => id !== null);
}).filter((id: any): id is string => id !== null);
if (noteIds.length === 0) return [];
const notes = await this.notesRepository.findBy({
id: In(noteIds),

View file

@ -17,6 +17,7 @@ import { InstanceActorService } from '@/core/InstanceActorService.js';
import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
import { envOption } from '@/env.js';
@Injectable()
export class MetaEntityService {
@ -66,7 +67,7 @@ export class MetaEntityService {
feedbackUrl: instance.feedbackUrl,
impressumUrl: instance.impressumUrl,
privacyPolicyUrl: instance.privacyPolicyUrl,
disableRegistration: instance.disableRegistration,
disableRegistration: instance.disableRegistration || envOption.disableRegistration,
emailRequiredForSignup: instance.emailRequiredForSignup,
canSkipInitialTutorial: instance.canSkipInitialTutorial,
enableHcaptcha: instance.enableHcaptcha,

View file

@ -12,6 +12,7 @@ const envOption = {
logJson: false,
withLogTime: false,
quiet: false,
disableRegistration: false,
};
for (const key of Object.keys(envOption) as (keyof typeof envOption)[]) {

View file

@ -79,4 +79,9 @@ export class MiSingleSignOnServiceProvider {
default: true,
})
public wantAssertionsSigned: boolean;
@Column('boolean', {
default: true,
})
public wantEmailAddressNormalized: boolean;
}

View file

@ -20,6 +20,7 @@ import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
import { bindThis } from '@/decorators.js';
import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js';
import { LoggerService } from '@/core/LoggerService.js';
import { envOption } from '@/env.js';
import { SigninService } from './SigninService.js';
import type { FastifyRequest, FastifyReply } from 'fastify';
import { randomUUID } from 'node:crypto';
@ -136,7 +137,7 @@ export class SignupApiService {
let ticket: MiRegistrationTicket | null = null;
if (instance.disableRegistration) {
if (instance.disableRegistration || envOption.disableRegistration) {
if (invitationCode == null || typeof invitationCode !== 'string') {
logger.error('Invalid request: invitation code is required.');
reply.code(400);

View file

@ -84,6 +84,10 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
wantEmailAddressNormalized: {
type: 'boolean',
optional: false, nullable: false,
},
},
},
} as const;
@ -101,6 +105,7 @@ export const paramDef = {
cipherAlgorithm: { type: 'string', nullable: true },
wantAuthnRequestsSigned: { type: 'boolean', nullable: false, default: false },
wantAssertionsSigned: { type: 'boolean', nullable: false, default: true },
wantEmailAddressNormalized: { type: 'boolean', nullable: false, default: true },
useCertificate: { type: 'boolean', nullable: false, default: true },
secret: { type: 'string', nullable: true },
},
@ -157,6 +162,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
cipherAlgorithm: ps.cipherAlgorithm ? ps.cipherAlgorithm : null,
wantAuthnRequestsSigned: ps.wantAuthnRequestsSigned,
wantAssertionsSigned: ps.wantAssertionsSigned,
wantEmailAddressNormalized: ps.wantEmailAddressNormalized,
}).then(r => this.singleSignOnServiceProviderRepository.findOneByOrFail({ id: r.identifiers[0].id }));
this.moderationLogService.log(me, 'createSSOServiceProvider', {
@ -178,6 +184,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
cipherAlgorithm: ssoServiceProvider.cipherAlgorithm,
wantAuthnRequestsSigned: ssoServiceProvider.wantAuthnRequestsSigned,
wantAssertionsSigned: ssoServiceProvider.wantAssertionsSigned,
wantEmailAddressNormalized: ssoServiceProvider.wantEmailAddressNormalized,
};
});
}

View file

@ -77,6 +77,10 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
wantEmailAddressNormalized: {
type: 'boolean',
optional: false, nullable: false,
},
},
},
},
@ -116,6 +120,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
cipherAlgorithm: service.cipherAlgorithm,
wantAuthnRequestsSigned: service.wantAuthnRequestsSigned,
wantAssertionsSigned: service.wantAssertionsSigned,
wantEmailAddressNormalized: service.wantEmailAddressNormalized,
}));
});
}

View file

@ -37,6 +37,7 @@ export const paramDef = {
cipherAlgorithm: { type: 'string', nullable: true },
wantAuthnRequestsSigned: { type: 'boolean', nullable: false },
wantAssertionsSigned: { type: 'boolean', nullable: false },
wantEmailAddressNormalized: { type: 'boolean', nullable: false },
regenerateCertificate: { type: 'boolean', nullable: true },
secret: { type: 'string', nullable: true },
},
@ -92,6 +93,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
cipherAlgorithm: ps.cipherAlgorithm !== '' ? ps.cipherAlgorithm : null,
wantAuthnRequestsSigned: ps.wantAuthnRequestsSigned,
wantAssertionsSigned: ps.wantAssertionsSigned,
wantEmailAddressNormalized: ps.wantEmailAddressNormalized,
});
const updatedService = await this.singleSignOnServiceProviderRepository.findOneByOrFail({ id: service.id });

View file

@ -180,7 +180,9 @@ export class JWTIdentifyProviderService {
preferred_username: user.username,
profile: `${this.config.url}/@${user.username}`,
picture: user.avatarUrl ?? undefined,
email: profile.emailVerified ? normalizeEmailAddress(profile.email) : `${user.username}@${this.config.hostname}`,
email: profile.emailVerified
? (ssoServiceProvider.wantEmailAddressNormalized ? normalizeEmailAddress(profile.email) : profile.email)
: `${user.username}@users.${this.config.hostname}`,
email_verified: profile.emailVerified,
mfa_enabled: profile.twoFactorEnabled,
updated_at: Math.floor((user.updatedAt?.getTime() ?? user.createdAt.getTime()) / 1000),

View file

@ -444,7 +444,9 @@ export class SAMLIdentifyProviderService {
'saml:Subject': {
'saml:NameID': {
'@Format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
'#text': profile.emailVerified ? normalizeEmailAddress(profile.email) : `${user.username}@${this.config.hostname}`,
'#text': profile.emailVerified
? (ssoServiceProvider.wantEmailAddressNormalized ? normalizeEmailAddress(profile.email) : profile.email)
: `${user.username}@users.${this.config.hostname}`,
},
'saml:SubjectConfirmation': {
'@Method': 'urn:oasis:names:tc:SAML:2.0:cm:bearer',
@ -569,7 +571,9 @@ export class SAMLIdentifyProviderService {
'@NameFormat': 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
'saml:AttributeValue': {
'@xsi:type': 'xs:string',
'#text': profile.emailVerified ? normalizeEmailAddress(profile.email) : `${user.username}@${this.config.hostname}`,
'#text': profile.emailVerified
? (ssoServiceProvider.wantEmailAddressNormalized ? normalizeEmailAddress(profile.email) : profile.email)
: `${user.username}@users.${this.config.hostname}`,
},
},
{

View file

@ -197,6 +197,7 @@ export class ClientServerService {
instanceUrl: this.config.url,
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)),
now: Date.now(),
extraHead: this.config.extraHead,
};
}
@ -433,7 +434,7 @@ export class ClientServerService {
return await reply.sendFile('/robots.txt', staticAssets);
});
// OpenSearch XML
/* OpenSearch XML
fastify.get('/opensearch.xml', async (request, reply) => {
const meta = await this.metaService.fetch();
@ -450,6 +451,7 @@ export class ClientServerService {
reply.header('Content-Type', 'application/opensearchdescription+xml');
return await reply.send(content);
});
*/
//#endregion

View file

@ -37,7 +37,6 @@ export class UrlPreviewService {
@bindThis
private wrap(url?: string | null): string | null {
if (!url) return null;
if (!RegExp(/^https?:\/\//).exec(url)) return url;
return appendQuery(
`${this.config.mediaProxy}/preview/${encodeURIComponent(omitHttps(url))}`,

View file

@ -73,6 +73,8 @@ html
script(src=`/assets/boot.${version}.js`)
| !{extraHead}
body
noscript: p
| JavaScriptを有効にしてください

View file

@ -7,18 +7,12 @@ services:
memlock: -1
environment:
DFLY_version_check: false
DFLY_tcp_backlog: 2048
DFLY_default_lua_flags: allow-undeclared-keys
DFLY_pipeline_squash: 0
DFLY_multi_exec_squash: false
DFLY_conn_io_threads: 4
DFLY_epoll_file_threads: 4
DFLY_proactor_threads: 4
ports:
- "127.0.0.1:56312:6379"
dbtest:
image: postgres:15
image: postgres:17
ports:
- "127.0.0.1:54312:5432"
environment:

View file

@ -25,7 +25,7 @@ describe('Drive', () => {
const marker = Math.random().toString();
const url = 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.jpg';
const url = 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.jpg';
const catcher = makeStreamCatcher(
alice,

View file

@ -104,7 +104,7 @@ describe('Webリソース', () => {
{ path: '/flush', type: HTML },
{ path: '/robots.txt', type: 'text/plain; charset=utf-8' },
{ path: '/favicon.ico', type: 'image/vnd.microsoft.icon' },
{ path: '/opensearch.xml', type: 'application/opensearchdescription+xml' },
// { path: '/opensearch.xml', type: 'application/opensearchdescription+xml' },
{ path: '/apple-touch-icon.png', type: 'image/png' },
{ path: '/twemoji/2764.svg', type: 'image/svg+xml' },
{ path: '/twemoji/2764-fe0f-200d-1f525.svg', type: 'image/svg+xml' },

View file

@ -43,7 +43,7 @@ describe('Note', () => {
});
test('ファイルを添付できる', async () => {
const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.jpg');
const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.jpg');
const res = await api('notes/create', {
fileIds: [file.id],
@ -55,7 +55,7 @@ describe('Note', () => {
}, 1000 * 10);
test('他人のファイルで怒られる', async () => {
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.jpg');
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.jpg');
const res = await api('notes/create', {
text: 'test',

View file

@ -354,8 +354,8 @@ describe('Timelines', () => {
await api('following/create', { userId: bob.id }, alice);
await sleep(1000);
const [bobFile, carolFile] = await Promise.all([
uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png'),
uploadUrl(carol, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png'),
uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png'),
uploadUrl(carol, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png'),
]);
const bobNote1 = await post(bob, { text: 'hi' });
const bobNote2 = await post(bob, { fileIds: [bobFile.id] });
@ -654,7 +654,7 @@ describe('Timelines', () => {
test.concurrent('[withFiles: true] ファイル付きノートのみ含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup()]);
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png');
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png');
const bobNote1 = await post(bob, { text: 'hi' });
const bobNote2 = await post(bob, { fileIds: [file.id] });
@ -794,7 +794,7 @@ describe('Timelines', () => {
test.concurrent('[withFiles: true] ファイル付きノートのみ含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup()]);
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png');
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png');
const bobNote1 = await post(bob, { text: 'hi' });
const bobNote2 = await post(bob, { fileIds: [file.id] });
@ -1008,7 +1008,7 @@ describe('Timelines', () => {
const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body);
await api('users/lists/push', { listId: list.id, userId: bob.id }, alice);
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png');
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png');
const bobNote1 = await post(bob, { text: 'hi' });
const bobNote2 = await post(bob, { fileIds: [file.id] });
@ -1167,7 +1167,7 @@ describe('Timelines', () => {
test.concurrent('[withFiles: true] ファイル付きノートのみ含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup()]);
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png');
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png');
const bobNote1 = await post(bob, { text: 'hi' });
const bobNote2 = await post(bob, { fileIds: [file.id] });

View file

@ -17,8 +17,8 @@ describe('users/notes', () => {
beforeAll(async () => {
alice = await signup({ username: 'alice' });
const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.jpg');
const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/MisskeyIO/misskey/io/packages/backend/test/resources/Lenna.png');
const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.jpg');
const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/MisskeyIO/misskey/main/packages/backend/test/resources/Lenna.png');
jpgNote = await post(alice, {
fileIds: [jpg.id],
});

View file

@ -6,6 +6,7 @@
process.env.NODE_ENV = 'test';
import { jest } from '@jest/globals';
import { IsNull, Not } from 'typeorm';
import { ModuleMocker } from 'jest-mock';
import { Test } from '@nestjs/testing';
import { GlobalModule } from '@/GlobalModule.js';
@ -103,10 +104,10 @@ describe('AnnouncementService', () => {
afterEach(async () => {
await Promise.all([
app.get(DI.metasRepository).delete({}),
usersRepository.delete({}),
announcementsRepository.delete({}),
announcementReadsRepository.delete({}),
app.get(DI.metasRepository).delete({ id: Not(IsNull()) }),
usersRepository.delete({ id: Not(IsNull()) }),
announcementsRepository.delete({ id: Not(IsNull()) }),
announcementReadsRepository.delete({ id: Not(IsNull()) }),
]);
await app.close();

View file

@ -8,6 +8,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
process.env.NODE_ENV = 'test';
import { jest } from '@jest/globals';
import { IsNull, Not } from 'typeorm';
import { ModuleMocker } from 'jest-mock';
import { Test } from '@nestjs/testing';
import * as lolex from '@sinonjs/fake-timers';
@ -132,10 +133,10 @@ describe('RoleService', () => {
clock.uninstall();
await Promise.all([
app.get(DI.metasRepository).delete({}),
usersRepository.delete({}),
rolesRepository.delete({}),
roleAssignmentsRepository.delete({}),
app.get(DI.metasRepository).delete({ id: Not(IsNull()) }),
usersRepository.delete({ id: Not(IsNull()) }),
rolesRepository.delete({ id: Not(IsNull()) }),
roleAssignmentsRepository.delete({ id: Not(IsNull()) }),
]);
await app.close();

View file

@ -27,27 +27,27 @@
"@rollup/pluginutils": "5.1.4",
"@syuilo/aiscript": "0.19.0",
"@tabler/icons-webfont": "3.31.0",
"@twemoji/parser": "15.1.1",
"@vitejs/plugin-vue": "5.2.3",
"@twemoji/parser": "16.0.0",
"@vitejs/plugin-vue": "5.2.4",
"@vue/compiler-sfc": "3.5.13",
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.15",
"aiscript-vscode": "managed",
"astring": "1.9.0",
"broadcast-channel": "7.1.0",
"buraha": "0.0.1",
"canvas-confetti": "1.9.3",
"chart.js": "4.4.8",
"chart.js": "4.4.9",
"chartjs-adapter-date-fns": "3.0.0",
"chartjs-chart-matrix": "3.0.0",
"chartjs-plugin-gradient": "0.6.1",
"chartjs-plugin-zoom": "2.2.0",
"chromatic": "11.27.0",
"chromatic": "11.28.2",
"compare-versions": "6.1.1",
"cropperjs": "2.0.0",
"date-fns": "4.1.0",
"escape-regexp": "0.0.1",
"estree-walker": "3.0.3",
"eventemitter3": "5.0.1",
"idb-keyval": "6.2.1",
"idb-keyval": "6.2.2",
"insert-text-at-cursor": "0.3.0",
"is-file-animated": "1.0.2",
"json5": "2.2.3",
@ -58,88 +58,88 @@
"misskey-reversi": "workspace:*",
"photoswipe": "5.4.4",
"punycode.js": "2.3.1",
"rollup": "4.38.0",
"sanitize-html": "2.15.0",
"sass": "1.86.0",
"shiki": "3.2.1",
"rollup": "4.40.2",
"sanitize-html": "2.16.0",
"sass": "1.88.0",
"shiki": "3.4.0",
"strict-event-emitter-types": "2.0.0",
"textarea-caret": "3.1.0",
"three": "0.175.0",
"three": "0.176.0",
"throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0",
"tsc-alias": "1.8.13",
"tsc-alias": "1.8.16",
"tsconfig-paths": "4.2.0",
"typescript": "5.8.2",
"typescript": "5.8.3",
"uuid": "11.1.0",
"v-code-diff": "1.13.1",
"vite": "6.2.4",
"vite": "6.3.5",
"vue": "3.5.13",
"vue-gtag": "3.2.0",
"vue-gtag": "3.5.0",
"vuedraggable": "next",
"webgl-audiovisualizer": "github:tar-bin/webgl-audiovisualizer"
"webgl-audiovisualizer": "managed"
},
"devDependencies": {
"@misskey-dev/eslint-plugin": "1.0.0",
"@misskey-dev/summaly": "github:MisskeyIO/summaly#5.1.3",
"@storybook/addon-actions": "8.6.11",
"@storybook/addon-essentials": "8.6.11",
"@storybook/addon-interactions": "8.6.11",
"@storybook/addon-links": "8.6.11",
"@storybook/addon-mdx-gfm": "8.6.11",
"@storybook/addon-storysource": "8.6.11",
"@storybook/blocks": "8.6.11",
"@storybook/components": "8.6.11",
"@storybook/core-events": "8.6.11",
"@storybook/manager-api": "8.6.11",
"@storybook/preview-api": "8.6.11",
"@storybook/react": "8.6.11",
"@storybook/react-vite": "8.6.11",
"@storybook/test": "8.6.11",
"@storybook/theming": "8.6.11",
"@storybook/types": "8.6.11",
"@storybook/vue3": "8.6.11",
"@storybook/vue3-vite": "8.6.11",
"@misskey-dev/summaly": "managed",
"@storybook/addon-actions": "8.6.12",
"@storybook/addon-essentials": "8.6.12",
"@storybook/addon-interactions": "8.6.12",
"@storybook/addon-links": "8.6.12",
"@storybook/addon-mdx-gfm": "8.6.12",
"@storybook/addon-storysource": "8.6.12",
"@storybook/blocks": "8.6.12",
"@storybook/components": "8.6.12",
"@storybook/core-events": "8.6.12",
"@storybook/manager-api": "8.6.12",
"@storybook/preview-api": "8.6.12",
"@storybook/react": "8.6.12",
"@storybook/react-vite": "8.6.12",
"@storybook/test": "8.6.12",
"@storybook/theming": "8.6.12",
"@storybook/types": "8.6.12",
"@storybook/vue3": "8.6.12",
"@storybook/vue3-vite": "8.6.12",
"@testing-library/vue": "8.1.0",
"@types/canvas-confetti": "^1.6.4",
"@types/escape-regexp": "0.0.3",
"@types/estree": "1.0.7",
"@types/matter-js": "0.19.8",
"@types/micromatch": "4.0.9",
"@types/node": "22.13.14",
"@types/punycode.js": "npm:@types/punycode@2.1.4",
"@types/sanitize-html": "2.15.0",
"@types/three": "0.175.0",
"@types/node": "22.15.17",
"@types/punycode.js": "managed",
"@types/sanitize-html": "2.16.0",
"@types/three": "0.176.0",
"@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6",
"@types/ws": "8.18.0",
"@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"@vitest/coverage-v8": "3.1.1",
"@vitest/coverage-v8": "3.1.3",
"@vue/runtime-core": "3.5.13",
"acorn": "8.14.1",
"cross-env": "7.0.3",
"cypress": "14.2.1",
"cypress": "14.3.3",
"eslint": "8.57.1",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-vue": "9.32.0",
"fast-glob": "3.3.3",
"happy-dom": "17.4.4",
"happy-dom": "17.4.7",
"intersection-observer": "0.12.2",
"micromatch": "4.0.8",
"msw": "2.7.3",
"msw": "2.8.2",
"msw-storybook-addon": "2.0.4",
"nodemon": "3.1.9",
"nodemon": "3.1.10",
"prettier": "3.5.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"start-server-and-test": "2.0.11",
"storybook": "8.6.11",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"storybook": "8.6.12",
"storybook-addon-misskey-theme": "managed",
"vite-plugin-turbosnap": "1.0.3",
"vitest": "3.1.1",
"vitest": "3.1.3",
"vitest-fetch-mock": "0.3.0",
"vue-component-type-helpers": "2.2.8",
"vue-component-type-helpers": "2.2.10",
"vue-eslint-parser": "9.4.3",
"vue-tsc": "2.2.8"
"vue-tsc": "2.2.10"
}
}

View file

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="el"
style="word-break: break-all;"
class="_link"
:[attr]="self ? url.substring(local.length) : url"
:[attr]="maybeRelativeUrl"
:rel="rel ?? 'nofollow noopener'"
:target="target"
:behavior="props.navigationBehavior"
@ -28,7 +28,8 @@ import { useTooltip } from '@/scripts/use-tooltip.js';
import { warningExternalWebsite } from '@/scripts/warning-external-website.js';
import * as os from '@/os.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { MkABehavior } from '@/components/global/MkA.vue';
import type { MkABehavior } from '@/components/global/MkA.vue';
import { maybeMakeRelative } from '@/scripts/url.js';
const props = withDefaults(defineProps<{
url: string;
@ -39,7 +40,8 @@ const props = withDefaults(defineProps<{
hideIcon: false,
});
const self = props.url.startsWith(local);
const maybeRelativeUrl = maybeMakeRelative(props.url, local);
const self = maybeRelativeUrl !== props.url;
const attr = self ? 'to' : 'href';
const target = self ? null : '_blank';

View file

@ -24,7 +24,11 @@ async function fetchSkebStatus() {
return;
}
userSkebStatus.value = await misskeyApiGet('users/get-skeb-status', { userId: props.userId });
try {
userSkebStatus.value = await misskeyApiGet('users/get-skeb-status', { userId: props.userId });
} catch {
userSkebStatus.value = null;
}
}
if (props.role.behavior === 'skeb') {

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div v-adaptive-bg class="_panel" style="position: relative;">
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"></div>
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${user.bannerUrl})` } : ''"></div>
<MkAvatar :class="$style.avatar" :user="user" indicator/>
<div :class="$style.title">
<div :class="$style.name"><MkUserName :user="user" :nowrap="false"/></div>

View file

@ -47,13 +47,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<component
:is="self ? 'MkA' : 'a'"
:class="[$style.link, { [$style.compact]: compact }]"
:[attr]="self ? url.substring(local.length) : url"
:[attr]="maybeRelativeUrl"
rel="nofollow noopener"
:target="target"
:title="url"
@click="(ev: MouseEvent) => warningExternalWebsite(ev, url)"
>
<div v-if="thumbnail" :class="[$style.thumbnail, { [$style.thumbnailBlur]: sensitive }]" :style="defaultStore.state.dataSaver.urlPreview ? '' : `background-image: url('${thumbnail}')`">
<div v-if="thumbnail" :class="[$style.thumbnail, { [$style.thumbnailBlur]: sensitive }]" :style="defaultStore.state.dataSaver.urlPreview ? '' : { backgroundImage: `url('${thumbnail}')` }">
</div>
<article :class="$style.body">
<header :class="$style.header">
@ -101,6 +101,7 @@ import MkButton from '@/components/MkButton.vue';
import { versatileLang } from '@/scripts/intl-const.js';
import { defaultStore } from '@/store.js';
import { warningExternalWebsite } from '@/scripts/warning-external-website.js';
import { maybeMakeRelative } from '@/scripts/url.js';
type SummalyResult = Awaited<ReturnType<typeof summaly>>;
@ -118,7 +119,8 @@ const props = withDefaults(defineProps<{
const MOBILE_THRESHOLD = 500;
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
const self = props.url.startsWith(local);
const maybeRelativeUrl = maybeMakeRelative(props.url, local);
const self = maybeRelativeUrl !== props.url;
const attr = self ? 'to' : 'href';
const target = self ? null : '_blank';
const fetching = ref(true);

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div class="_panel" :class="$style.root">
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"></div>
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${user.bannerUrl})` } : ''"></div>
<MkAvatar :class="$style.avatar" :user="user" indicator/>
<div :class="$style.title">
<MkA :class="$style.name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA>

View file

@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<div v-if="showing" :class="$style.root" class="_popup _shadow" :style="{ zIndex, top: top + 'px', left: left + 'px' }" @mouseover="() => { emit('mouseover'); }" @mouseleave="() => { emit('mouseleave'); }">
<div v-if="user != null">
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''">
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${user.bannerUrl})` } : ''">
<span v-if="$i && $i.id != user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
</div>
<svg viewBox="0 0 128 128" :class="$style.avatarBack">

View file

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="el"
:class="$style.root"
class="_link"
:[attr]="self ? props.url.substring(local.length) : props.url"
:[attr]="maybeRelativeUrl"
:rel="rel ?? 'nofollow noopener'"
:target="target"
:behavior="props.navigationBehavior"
@ -40,7 +40,8 @@ import { useTooltip } from '@/scripts/use-tooltip.js';
import { safeURIDecode } from '@/scripts/safe-uri-decode.js';
import { warningExternalWebsite } from '@/scripts/warning-external-website.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { MkABehavior } from '@/components/global/MkA.vue';
import type { MkABehavior } from '@/components/global/MkA.vue';
import { maybeMakeRelative } from '@/scripts/url.js';
const props = withDefaults(defineProps<{
url: string;
@ -51,7 +52,8 @@ const props = withDefaults(defineProps<{
showUrlPreview: true,
});
const self = props.url.startsWith(local);
const maybeRelativeUrl = maybeMakeRelative(props.url, local);
const self = maybeRelativeUrl !== props.url;
const url = new URL(props.url);
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('invalid url');
const el = ref();

View file

@ -206,6 +206,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="service.wantAssertionsSigned">
<template #label>Want Assertions Signed</template>
</MkSwitch>
<MkSwitch v-model="service.wantEmailAddressNormalized">
<template #label>Want Email Address Normalized</template>
</MkSwitch>
<MkSwitch v-model="service.useCertificate" :disabled="!!service.createdAt">
<template #label>Use Certificate</template>
</MkSwitch>
@ -422,6 +425,7 @@ function ssoServiceAddNew() {
cipherAlgorithm: '',
wantAuthnRequestsSigned: false,
wantAssertionsSigned: true,
wantEmailAddressNormalized: true,
regenerateCertificate: false,
});
}
@ -453,6 +457,7 @@ async function ssoServiceSave(service) {
cipherAlgorithm: service.cipherAlgorithm,
wantAuthnRequestsSigned: service.wantAuthnRequestsSigned,
wantAssertionsSigned: service.wantAssertionsSigned,
wantEmailAddressNormalized: service.wantEmailAddressNormalized,
};
if (service.createdAt !== undefined) {

View file

@ -363,7 +363,11 @@ async function fetchSkebStatus() {
return;
}
userSkebStatus.value = await misskeyApiGet('users/get-skeb-status', { userId: props.user.id });
try {
userSkebStatus.value = await misskeyApiGet('users/get-skeb-status', { userId: props.user.id });
} catch {
userSkebStatus.value = null;
}
}
function buildSkebStatus(): string {

View file

@ -51,7 +51,9 @@ export function createAiScriptEnv(opts) {
}),
'Mk:api': values.FN_NATIVE(async ([ep, param, token]) => {
utils.assertString(ep);
if (ep.value.includes('://')) throw new Error('invalid endpoint');
if (ep.value.includes('://') || ep.value.includes('..')) {
throw new Error('invalid endpoint');
}
if (token) {
utils.assertString(token);
// バグがあればundefinedもあり得るため念のため

View file

@ -6,16 +6,30 @@
import * as Misskey from 'misskey-js';
export function shouldCollapsed(note: Misskey.entities.Note, urls: string[]): boolean {
const collapsed = note.cw == null && note.text != null && (
(note.text.includes('$[x2')) ||
(note.text.includes('$[x3')) ||
(note.text.includes('$[x4')) ||
(note.text.includes('$[scale')) ||
(note.text.split('\n').length > 9) ||
(note.text.length > 500) ||
(note.files.length >= 5) ||
(urls.length >= 4)
);
if (note.cw != null) {
return false;
}
return collapsed;
if (note.text != null) {
if (
note.text.includes('$[x2') ||
note.text.includes('$[x3') ||
note.text.includes('$[x4') ||
note.text.includes('$[scale') ||
note.text.split('\n').length > 9 ||
note.text.length > 500
) {
return true;
}
}
if (urls.length >= 4) {
return true;
}
if (note.files != null && note.files.length >= 5) {
return true;
}
return false;
}

View file

@ -27,3 +27,20 @@ export function omitHttps(url: string): string {
if (url.startsWith('https%3A%2F%2F')) return url.slice(14);
return url;
}
export function maybeMakeRelative(urlStr: string, baseStr: string): string {
try {
const baseObj = new URL(baseStr);
const urlObj = new URL(urlStr);
/* in all places where maybeMakeRelative is used, baseStr is the
* instance's public URL, which can't have path components, so the
* relative URL will always have the whole path from the urlStr
*/
if (urlObj.origin === baseObj.origin) {
return urlObj.pathname + urlObj.search + urlObj.hash;
}
return urlStr;
} catch {
return '';
}
}

View file

@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div
v-for="(image, i) in images" :key="i"
:class="$style.img"
:style="`background-image: url(${thumbnail(image)})`"
:style="{ backgroundImage: `url(${thumbnail(image)})` }"
></div>
</div>
</div>

View file

@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<rect
x="-2" y="-2"
:width="viewBoxX + 4" :height="viewBoxY + 4"
:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"
:style="{ stroke: 'none', fill: `url(#${ cpuGradientId })`, mask: `url(#${ cpuMaskId })` }"
/>
<text x="1" y="5">CPU <tspan>{{ cpuP }}%</tspan></text>
</svg>
@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<rect
x="-2" y="-2"
:width="viewBoxX + 4" :height="viewBoxY + 4"
:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"
:style="{ stroke: 'none', fill: `url(#${ memGradientId })`, mask: `url(#${ memMaskId })` }"
/>
<text x="1" y="5">MEM <tspan>{{ memP }}%</tspan></text>
</svg>

View file

@ -26,21 +26,21 @@
"devDependencies": {
"@misskey-dev/eslint-plugin": "1.0.0",
"@types/matter-js": "0.19.8",
"@types/node": "22.13.14",
"@types/node": "22.15.17",
"@types/seedrandom": "3.0.8",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"eslint": "8.57.1",
"nodemon": "3.1.9",
"typescript": "5.8.2"
"nodemon": "3.1.10",
"typescript": "5.8.3"
},
"files": [
"built"
],
"dependencies": {
"esbuild": "0.25.2",
"esbuild": "managed",
"eventemitter3": "5.0.1",
"glob": "11.0.1",
"glob": "11.0.2",
"matter-js": "0.20.0",
"seedrandom": "3.0.5"
}

View file

@ -9,15 +9,15 @@
"devDependencies": {
"@misskey-dev/eslint-plugin": "1.0.0",
"@readme/openapi-parser": "3.0.1",
"@types/node": "22.13.14",
"@types/node": "22.15.17",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"eslint": "8.57.1",
"openapi-types": "12.1.3",
"openapi-typescript": "6.7.6",
"ts-case-convert": "2.1.0",
"tsx": "4.19.3",
"typescript": "5.8.2"
"tsx": "4.19.4",
"typescript": "5.8.3"
},
"files": [
"built"

View file

@ -1,7 +1,7 @@
{
"type": "module",
"name": "misskey-js",
"version": "2024.5.0-oscar.24b",
"version": "2024.5.0-oscar.25",
"description": "Misskey SDK for JavaScript",
"types": "./built/dts/index.d.ts",
"exports": {
@ -35,11 +35,11 @@
"url": "git+https://github.com/misskey-dev/misskey.js.git"
},
"devDependencies": {
"@microsoft/api-extractor": "7.52.2",
"@microsoft/api-extractor": "7.52.8",
"@misskey-dev/eslint-plugin": "1.0.0",
"@swc/jest": "0.2.37",
"@swc/jest": "0.2.38",
"@types/jest": "29.5.14",
"@types/node": "22.13.14",
"@types/node": "22.15.17",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"eslint": "8.57.1",
@ -48,9 +48,9 @@
"jest-websocket-mock": "2.5.0",
"mock-socket": "9.3.1",
"ncp": "2.0.0",
"nodemon": "3.1.9",
"tsd": "0.31.2",
"typescript": "5.8.2"
"nodemon": "3.1.10",
"tsd": "0.32.0",
"typescript": "5.8.3"
},
"files": [
"built",
@ -58,8 +58,8 @@
"built/dts"
],
"dependencies": {
"@swc/cli": "0.6.0",
"@swc/core": "1.11.13",
"@swc/cli": "0.7.7",
"@swc/core": "1.11.24",
"eventemitter3": "5.0.1",
"reconnecting-websocket": "4.4.0"
}

View file

@ -11232,6 +11232,8 @@ export type operations = {
/** @default true */
wantAssertionsSigned?: boolean;
/** @default true */
wantEmailAddressNormalized?: boolean;
/** @default true */
useCertificate: boolean;
secret?: string | null;
};
@ -11258,6 +11260,7 @@ export type operations = {
cipherAlgorithm?: string | null;
wantAuthnRequestsSigned: boolean;
wantAssertionsSigned: boolean;
wantEmailAddressNormalized: boolean;
};
};
};
@ -11383,6 +11386,7 @@ export type operations = {
cipherAlgorithm?: string | null;
wantAuthnRequestsSigned: boolean;
wantAssertionsSigned: boolean;
wantEmailAddressNormalized: boolean;
})[];
};
};
@ -11439,6 +11443,7 @@ export type operations = {
cipherAlgorithm?: string | null;
wantAuthnRequestsSigned?: boolean;
wantAssertionsSigned?: boolean;
wantEmailAddressNormalized?: boolean;
regenerateCertificate?: boolean | null;
secret?: string | null;
};

View file

@ -25,17 +25,17 @@
},
"devDependencies": {
"@misskey-dev/eslint-plugin": "1.0.0",
"@types/node": "22.13.14",
"@types/node": "22.15.17",
"@typescript-eslint/eslint-plugin": "7.10.0",
"@typescript-eslint/parser": "7.10.0",
"eslint": "8.57.1",
"nodemon": "3.1.9",
"typescript": "5.8.2"
"nodemon": "3.1.10",
"typescript": "5.8.3"
},
"dependencies": {
"crc-32": "1.2.2",
"esbuild": "0.25.2",
"glob": "11.0.1"
"esbuild": "managed",
"glob": "11.0.2"
},
"files": [
"built"

View file

@ -9,18 +9,18 @@
"lint": "pnpm typecheck && pnpm eslint"
},
"dependencies": {
"esbuild": "0.25.2",
"idb-keyval": "6.2.1",
"esbuild": "managed",
"idb-keyval": "6.2.2",
"misskey-js": "workspace:*"
},
"devDependencies": {
"@misskey-dev/eslint-plugin": "1.0.0",
"@types/serviceworker": "0.0.127",
"@types/serviceworker": "0.0.134",
"@typescript-eslint/parser": "7.10.0",
"eslint": "8.57.1",
"eslint-plugin-import": "2.31.0",
"nodemon": "3.1.9",
"typescript": "5.8.2"
"nodemon": "3.1.10",
"typescript": "5.8.3"
},
"type": "module"
}

4573
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff