Merge branch 'main' into mk.absturztau.be
|
@ -133,3 +133,10 @@ redis:
|
||||||
#allowedPrivateNetworks: [
|
#allowedPrivateNetworks: [
|
||||||
# '127.0.0.1/32'
|
# '127.0.0.1/32'
|
||||||
#]
|
#]
|
||||||
|
|
||||||
|
# images used on error screens. You can use absolute or relative URLs.
|
||||||
|
# If you use relative URLs, be aware that the URL may be used on different pages/paths, so the path component should be absolute.
|
||||||
|
#images:
|
||||||
|
# info: /twemoji/1f440.svg
|
||||||
|
# notFound: /twemoji/2049.svg
|
||||||
|
# error: /twemoji/1f480.svg
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.autogen
|
.autogen
|
||||||
.vscode
|
|
||||||
.config
|
.config
|
||||||
|
.woodpecker
|
||||||
Dockerfile
|
Dockerfile
|
||||||
build/
|
build/
|
||||||
built/
|
built/
|
||||||
|
|
|
@ -2,9 +2,10 @@ root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 2
|
indent_size = 4
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
6
.gitattributes
vendored
|
@ -1,7 +1 @@
|
||||||
*.svg -diff -text
|
*.svg -diff -text
|
||||||
*.psd -diff -text
|
|
||||||
*.ai -diff -text
|
|
||||||
*.mqo -diff -text
|
|
||||||
*.glb -diff -text
|
|
||||||
*.blend -diff -text
|
|
||||||
*.afdesign -diff -text
|
|
||||||
|
|
2
.gitignore
vendored
|
@ -1,6 +1,6 @@
|
||||||
# Visual Studio Code
|
# Visual Studio Code
|
||||||
/.vscode
|
/.vscode
|
||||||
!/.vscode/extensions.json
|
/.vsls.json
|
||||||
|
|
||||||
# Intelij-IDEA
|
# Intelij-IDEA
|
||||||
/.idea
|
/.idea
|
||||||
|
|
8
.vscode/extensions.json
vendored
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"editorconfig.editorconfig",
|
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"Vue.volar",
|
|
||||||
"Vue.vscode-typescript-vue-plugin"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "http://json.schemastore.org/vsls",
|
|
||||||
"gitignore": "exclude"
|
|
||||||
}
|
|
22
.woodpecker/lint-sw.yml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
clone:
|
||||||
|
git:
|
||||||
|
image: woodpeckerci/plugin-git
|
||||||
|
settings:
|
||||||
|
depth: 1 # CI does not need commit history
|
||||||
|
recursive: true
|
||||||
|
|
||||||
|
pipeline:
|
||||||
|
install:
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
image: node:18.6.0
|
||||||
|
commands:
|
||||||
|
- yarn install
|
||||||
|
lint:
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
image: node:18.6.0
|
||||||
|
commands:
|
||||||
|
- yarn workspace sw run lint
|
|
@ -316,8 +316,8 @@ This does not apply when using the Composition API since reactivation is manual.
|
||||||
If you import json in TypeScript, the json file will be spit out together with the TypeScript file into the dist directory when compiling with tsc. This behavior may cause unintentional rewriting of files, so when importing json files, be sure to check whether the files are allowed to be rewritten or not. If you do not want the file to be rewritten, you should make sure that the file can be rewritten by importing the json file. If you do not want the file to be rewritten, use functions such as `fs.readFileSync` to read the file instead of importing it.
|
If you import json in TypeScript, the json file will be spit out together with the TypeScript file into the dist directory when compiling with tsc. This behavior may cause unintentional rewriting of files, so when importing json files, be sure to check whether the files are allowed to be rewritten or not. If you do not want the file to be rewritten, you should make sure that the file can be rewritten by importing the json file. If you do not want the file to be rewritten, use functions such as `fs.readFileSync` to read the file instead of importing it.
|
||||||
|
|
||||||
### Component style definitions do not have a `margin`
|
### Component style definitions do not have a `margin`
|
||||||
Setting the `margin` of a component may be confusing.
|
~~Setting the `margin` of a component may be confusing. Instead, it should always be the user of a component that sets a `margin`.~~
|
||||||
Instead, it should always be the user of a component that sets a `margin`.
|
This was a philosophy used previously. Hoever it now seems a better idea to add a default margin to the top level element of a component which can be easily overwritten on the usage of that component with a `style` attribute.
|
||||||
|
|
||||||
### Do not use the word "follow" in HTML class names
|
### Do not use the word "follow" in HTML class names
|
||||||
This has caused things to be blocked by an ad blocker in the past.
|
This has caused things to be blocked by an ad blocker in the past.
|
||||||
|
|
Before Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 317 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 200 KiB |
BIN
assets/ai.png
Before Width: | Height: | Size: 235 KiB |
Before Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 148 KiB |
BIN
assets/title.png
Before Width: | Height: | Size: 3.8 KiB |
42
docs/oauth.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# 3rd party access
|
||||||
|
Foundkey supports:
|
||||||
|
- OAuth 2.0 Authorization Code grant per [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749).
|
||||||
|
- OAuth Bearer Token Usage per [RFC 6750](https://www.rfc-editor.org/rfc/rfc6750).
|
||||||
|
- Proof Key for Code Exchange (PKCE) per [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636).
|
||||||
|
- OAuth 2.0 Authorization Server Metadata per [RFC 8414](https://www.rfc-editor.org/rfc/rfc8414.html).
|
||||||
|
|
||||||
|
# Discovery
|
||||||
|
Because the implementation may change in the future, it is recommended that you use OAuth 2.0 Authorization Server Metadata a.k.a. OpenID Connect Discovery.
|
||||||
|
In short, this means that to discover the URLs for the grant endpoints you should request `/.well-known/oauth-authorization-server`, which is a JSON object.
|
||||||
|
From there, `authorization_endpoint` and `token_endpoint` will probably be most interesting to you.
|
||||||
|
The definitions of all data fields are to be found in [RFC 8414, section 2](https://www.rfc-editor.org/rfc/rfc8414#section-2).
|
||||||
|
|
||||||
|
# App registration
|
||||||
|
Before using the OAuth grant you need to register your application.
|
||||||
|
Currently you will need to use the pre-existing Misskey API to register, though Dynamic Client Registration may be implemented at a later point.
|
||||||
|
(You'd be able to tell from the Authorization Server Metadata, see above.)
|
||||||
|
|
||||||
|
The data you will need to know before registering is the following:
|
||||||
|
- a name for your app,
|
||||||
|
- a short description to be shown to users,
|
||||||
|
- which API permissions you need, and
|
||||||
|
- the callback URL you want to use.
|
||||||
|
|
||||||
|
There can only be 1 callback URL per registration.
|
||||||
|
|
||||||
|
Note that you can specify permissions a 2nd time in the OAuth flow.
|
||||||
|
If you do not provide permissions again in the grant flow, the default is to use all permissions you gave when registering the app.
|
||||||
|
If you do provide permissions in the grant flow, permissions that were not registered will never be granted.
|
||||||
|
A list of available permissions can be viewed on any Foundkey instance by going to the API documentation at `/api-doc`.
|
||||||
|
|
||||||
|
To register your app you need to `POST` to `/api/app/create`.
|
||||||
|
The body of the request must be a JSON object with the following keys:
|
||||||
|
- `name` (string): a name for your app,
|
||||||
|
- `description` (string): a short description to be shown to users,
|
||||||
|
- `permission` (array of permission names) which API permissions you need, and
|
||||||
|
- `callbackUrl` (string): the callback URL you want to use.
|
||||||
|
|
||||||
|
If successful (HTTP response code 200) you will receive back a JSON object containing among other things:
|
||||||
|
- `id` (string): the client ID
|
||||||
|
- `secret` (string): the client secret
|
||||||
|
With these credentials you should be able to use the Authorization Code grant to obtain authorization.
|
|
@ -36,7 +36,7 @@ gulp.task('copy:client:locales', cb => {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build:backend:script', () => {
|
gulp.task('build:backend:script', () => {
|
||||||
return gulp.src(['./packages/backend/src/server/web/boot.js', './packages/backend/src/server/web/bios.js', './packages/backend/src/server/web/cli.js'])
|
return gulp.src(['./packages/backend/src/server/web/boot.js'])
|
||||||
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
||||||
.pipe(terser({
|
.pipe(terser({
|
||||||
toplevel: true
|
toplevel: true
|
||||||
|
@ -45,7 +45,7 @@ gulp.task('build:backend:script', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build:backend:style', () => {
|
gulp.task('build:backend:style', () => {
|
||||||
return gulp.src(['./packages/backend/src/server/web/style.css', './packages/backend/src/server/web/bios.css', './packages/backend/src/server/web/cli.css'])
|
return gulp.src(['./packages/backend/src/server/web/style.css'])
|
||||||
.pipe(cssnano({
|
.pipe(cssnano({
|
||||||
zindex: false
|
zindex: false
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -293,9 +293,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "الصفحات"
|
pages: "الصفحات"
|
||||||
integration: "التكامل"
|
|
||||||
connectService: "اتصل"
|
|
||||||
disconnectService: "اقطع الاتصال"
|
|
||||||
enableLocalTimeline: "تفعيل الخيط المحلي"
|
enableLocalTimeline: "تفعيل الخيط المحلي"
|
||||||
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
|
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
|
||||||
disablingTimelinesInfo: "سيتمكن المديرون والمشرفون من الوصول إلى كل الخيوط الزمنية\
|
disablingTimelinesInfo: "سيتمكن المديرون والمشرفون من الوصول إلى كل الخيوط الزمنية\
|
||||||
|
@ -402,7 +399,6 @@ normalPassword: "الكلمة السرية جيدة"
|
||||||
strongPassword: "الكلمة السرية قوية"
|
strongPassword: "الكلمة السرية قوية"
|
||||||
passwordMatched: "التطابق صحيح!"
|
passwordMatched: "التطابق صحيح!"
|
||||||
passwordNotMatched: "غير متطابقتان"
|
passwordNotMatched: "غير متطابقتان"
|
||||||
signinWith: "الولوج عبر {x}"
|
|
||||||
signinFailed: "فشل الولوج، خطأ في اسم المستخدم أو كلمة المرور."
|
signinFailed: "فشل الولوج، خطأ في اسم المستخدم أو كلمة المرور."
|
||||||
tapSecurityKey: "أنقر مفتاح الأمان"
|
tapSecurityKey: "أنقر مفتاح الأمان"
|
||||||
or: "أو"
|
or: "أو"
|
||||||
|
|
|
@ -308,9 +308,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "পৃষ্ঠা"
|
pages: "পৃষ্ঠা"
|
||||||
integration: "ইন্টিগ্রেশন"
|
|
||||||
connectService: "সংযুক্ত করুন"
|
|
||||||
disconnectService: "সংযোগ বিচ্ছিন্ন করুন"
|
|
||||||
enableLocalTimeline: "স্থানীয় টাইমলাইন চালু করুন"
|
enableLocalTimeline: "স্থানীয় টাইমলাইন চালু করুন"
|
||||||
enableGlobalTimeline: "গ্লোবাল টাইমলাইন চালু করুন"
|
enableGlobalTimeline: "গ্লোবাল টাইমলাইন চালু করুন"
|
||||||
disablingTimelinesInfo: "আপনি এই টাইমলাইনগুলি বন্ধ করলেও প্রশাসক এবং মডারেটররা এই\
|
disablingTimelinesInfo: "আপনি এই টাইমলাইনগুলি বন্ধ করলেও প্রশাসক এবং মডারেটররা এই\
|
||||||
|
@ -417,7 +414,6 @@ normalPassword: "সাধারণ পাসওয়ার্ড"
|
||||||
strongPassword: "শক্তিশালী পাসওয়ার্ড"
|
strongPassword: "শক্তিশালী পাসওয়ার্ড"
|
||||||
passwordMatched: "মিলেছে"
|
passwordMatched: "মিলেছে"
|
||||||
passwordNotMatched: "মিলেনি"
|
passwordNotMatched: "মিলেনি"
|
||||||
signinWith: "{x} এর সাহায্যে সাইন ইন করুন"
|
|
||||||
signinFailed: "লগ ইন করা যায়নি। আপনার ব্যবহারকারীর নাম এবং পাসওয়ার্ড চেক করুন."
|
signinFailed: "লগ ইন করা যায়নি। আপনার ব্যবহারকারীর নাম এবং পাসওয়ার্ড চেক করুন."
|
||||||
tapSecurityKey: "সিকিউরিটি কী স্পর্শ করুন"
|
tapSecurityKey: "সিকিউরিটি কী স্পর্শ করুন"
|
||||||
or: "অথবা"
|
or: "অথবা"
|
||||||
|
|
|
@ -277,9 +277,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Stránky"
|
pages: "Stránky"
|
||||||
integration: "Integrace"
|
|
||||||
connectService: "Připojit"
|
|
||||||
disconnectService: "Odpojit"
|
|
||||||
enableLocalTimeline: "Povolit lokální čas"
|
enableLocalTimeline: "Povolit lokální čas"
|
||||||
enableGlobalTimeline: "Povolit globální čas"
|
enableGlobalTimeline: "Povolit globální čas"
|
||||||
enableRegistration: "Povolit registraci novým uživatelům"
|
enableRegistration: "Povolit registraci novým uživatelům"
|
||||||
|
@ -353,7 +350,6 @@ normalPassword: "Dobré heslo"
|
||||||
strongPassword: "Silné heslo"
|
strongPassword: "Silné heslo"
|
||||||
passwordMatched: "Hesla se schodují"
|
passwordMatched: "Hesla se schodují"
|
||||||
passwordNotMatched: "Hesla se neschodují"
|
passwordNotMatched: "Hesla se neschodují"
|
||||||
signinWith: "Přihlásit se s {x}"
|
|
||||||
signinFailed: "Nelze se přihlásit. Zkontrolujte prosím své uživatelské jméno a heslo."
|
signinFailed: "Nelze se přihlásit. Zkontrolujte prosím své uživatelské jméno a heslo."
|
||||||
or: "Nebo"
|
or: "Nebo"
|
||||||
language: "Jazyk"
|
language: "Jazyk"
|
||||||
|
|
|
@ -321,9 +321,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Seiten"
|
pages: "Seiten"
|
||||||
integration: "Integration"
|
|
||||||
connectService: "Verbinden"
|
|
||||||
disconnectService: "Trennen"
|
|
||||||
enableLocalTimeline: "Lokale Chronik aktivieren"
|
enableLocalTimeline: "Lokale Chronik aktivieren"
|
||||||
enableGlobalTimeline: "Globale Chronik aktivieren"
|
enableGlobalTimeline: "Globale Chronik aktivieren"
|
||||||
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle\
|
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle\
|
||||||
|
@ -433,7 +430,6 @@ normalPassword: "Durchschnittliches Passwort"
|
||||||
strongPassword: "Starkes Passwort"
|
strongPassword: "Starkes Passwort"
|
||||||
passwordMatched: "Stimmt überein"
|
passwordMatched: "Stimmt überein"
|
||||||
passwordNotMatched: "Stimmt nicht überein"
|
passwordNotMatched: "Stimmt nicht überein"
|
||||||
signinWith: "Mit {x} anmelden"
|
|
||||||
signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort."
|
signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort."
|
||||||
tapSecurityKey: "Tippe deinen Sicherheitsschlüssel an"
|
tapSecurityKey: "Tippe deinen Sicherheitsschlüssel an"
|
||||||
or: "Oder"
|
or: "Oder"
|
||||||
|
@ -1373,18 +1369,6 @@ recommended: "Empfehlung"
|
||||||
check: "Check"
|
check: "Check"
|
||||||
maxCustomEmojiPicker: Maximale Anzahl vorgeschlagener benutzerdefinierter Emoji
|
maxCustomEmojiPicker: Maximale Anzahl vorgeschlagener benutzerdefinierter Emoji
|
||||||
maxUnicodeEmojiPicker: Maximale Anzahl vorgeschlagener Unicode-Emoji
|
maxUnicodeEmojiPicker: Maximale Anzahl vorgeschlagener Unicode-Emoji
|
||||||
_services:
|
|
||||||
_discord:
|
|
||||||
connected: 'Discord: @{username}#{discriminator} wurde mit Foundkey-Account @{mkUsername}
|
|
||||||
verknüpft!'
|
|
||||||
disconnected: Discord-Verknüpfung wurde entfernt.
|
|
||||||
_twitter:
|
|
||||||
connected: Twitter-Account @{twitterUserName} wurde mit Foundkey-Account @{userName}
|
|
||||||
verknüpft!
|
|
||||||
disconnected: Twitter-Verknüpfung wurde entfernt.
|
|
||||||
_github:
|
|
||||||
connected: GitHub-Account @{login} wurde mit Foundkey-Account @{userName} verknüpft!
|
|
||||||
disconnected: GitHub-Verknüpfung wurde entfernt.
|
|
||||||
documentation: Dokumentation
|
documentation: Dokumentation
|
||||||
signinHistoryExpires: Frühere Login-Versuche werden aus Datenschutzgründen nach 60
|
signinHistoryExpires: Frühere Login-Versuche werden aus Datenschutzgründen nach 60
|
||||||
Tagen automatisch gelöscht.
|
Tagen automatisch gelöscht.
|
||||||
|
|
|
@ -96,6 +96,8 @@ unfollow: "Unfollow"
|
||||||
followRequestPending: "Follow request pending"
|
followRequestPending: "Follow request pending"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
unrenote: "Take back renote"
|
unrenote: "Take back renote"
|
||||||
|
unrenoteAll: "Take back all renotes"
|
||||||
|
unrenoteAllConfirm: "Are you sure that you want to take back all renotes of this note?"
|
||||||
quote: "Quote"
|
quote: "Quote"
|
||||||
pinnedNote: "Pinned note"
|
pinnedNote: "Pinned note"
|
||||||
you: "You"
|
you: "You"
|
||||||
|
@ -187,7 +189,7 @@ clearCachedFiles: "Clear cache"
|
||||||
clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote files?"
|
clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote files?"
|
||||||
blockedInstances: "Blocked Instances"
|
blockedInstances: "Blocked Instances"
|
||||||
blockedInstancesDescription: "List the hostnames of the instances that you want to\
|
blockedInstancesDescription: "List the hostnames of the instances that you want to\
|
||||||
\ block. Listed instances will no longer be able to communicate with this instance. Non-ASCII domain names must be encoded in punycode. You can use an asterisk (*) as a placeholder for zero or more character(s)."
|
\ block. Listed instances will no longer be able to communicate with this instance. Non-ASCII domain names must be encoded in punycode. Subdomains of the listed instances will also be blocked."
|
||||||
muteAndBlock: "Mutes and Blocks"
|
muteAndBlock: "Mutes and Blocks"
|
||||||
mutedUsers: "Muted users"
|
mutedUsers: "Muted users"
|
||||||
blockedUsers: "Blocked users"
|
blockedUsers: "Blocked users"
|
||||||
|
@ -311,9 +313,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Pages"
|
pages: "Pages"
|
||||||
integration: "Integration"
|
|
||||||
connectService: "Connect"
|
|
||||||
disconnectService: "Disconnect"
|
|
||||||
enableLocalTimeline: "Enable local timeline"
|
enableLocalTimeline: "Enable local timeline"
|
||||||
enableGlobalTimeline: "Enable global timeline"
|
enableGlobalTimeline: "Enable global timeline"
|
||||||
disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all\
|
disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all\
|
||||||
|
@ -420,7 +419,6 @@ normalPassword: "Average password"
|
||||||
strongPassword: "Strong password"
|
strongPassword: "Strong password"
|
||||||
passwordMatched: "Matches"
|
passwordMatched: "Matches"
|
||||||
passwordNotMatched: "Does not match"
|
passwordNotMatched: "Does not match"
|
||||||
signinWith: "Sign in with {x}"
|
|
||||||
signinFailed: "Unable to sign in. The entered username or password is incorrect."
|
signinFailed: "Unable to sign in. The entered username or password is incorrect."
|
||||||
tapSecurityKey: "Tap your security key"
|
tapSecurityKey: "Tap your security key"
|
||||||
or: "Or"
|
or: "Or"
|
||||||
|
@ -829,6 +827,10 @@ setTag: "Set tag"
|
||||||
addTag: "Add tag"
|
addTag: "Add tag"
|
||||||
removeTag: "Remove tag"
|
removeTag: "Remove tag"
|
||||||
externalCssSnippets: "Some CSS snippets for your inspiration (not managed by FoundKey)"
|
externalCssSnippets: "Some CSS snippets for your inspiration (not managed by FoundKey)"
|
||||||
|
oauthErrorGoBack: "An error happened while trying to authenticate a 3rd party app.\
|
||||||
|
\ Please go back and try again."
|
||||||
|
appAuthorization: "App authorization"
|
||||||
|
noPermissionsRequested: "(No permissions requested.)"
|
||||||
_emailUnavailable:
|
_emailUnavailable:
|
||||||
used: "This email address is already being used"
|
used: "This email address is already being used"
|
||||||
format: "The format of this email address is invalid"
|
format: "The format of this email address is invalid"
|
||||||
|
@ -1079,38 +1081,37 @@ _2fa:
|
||||||
\ authentication via hardware security keys that support FIDO2 to further secure\
|
\ authentication via hardware security keys that support FIDO2 to further secure\
|
||||||
\ your account."
|
\ your account."
|
||||||
_permissions:
|
_permissions:
|
||||||
"read:account": "View your account information"
|
"read:account": "Read account information"
|
||||||
"write:account": "Edit your account information"
|
"write:account": "Edit account information"
|
||||||
"read:blocks": "View your list of blocked users"
|
"read:blocks": "Read which users are blocked"
|
||||||
"write:blocks": "Edit your list of blocked users"
|
"write:blocks": "Block and unblock users"
|
||||||
"read:drive": "Access your Drive files and folders"
|
"read:drive": "List files and folders in the drive"
|
||||||
"write:drive": "Edit or delete your Drive files and folders"
|
"write:drive": "Create, change and delete files in the drive"
|
||||||
"read:favorites": "View your list of favorites"
|
"read:favorites": "List favourited notes"
|
||||||
"write:favorites": "Edit your list of favorites"
|
"write:favorites": "Favorite and unfavorite notes"
|
||||||
"read:following": "View information on who you follow"
|
"read:following": "List followed and following users"
|
||||||
"write:following": "Follow or unfollow other accounts"
|
"write:following": "Follow and unfollow other users"
|
||||||
"read:messaging": "View your chats"
|
"read:messaging": "View chat messages and history"
|
||||||
"write:messaging": "Compose or delete chat messages"
|
"write:messaging": "Create and delete chat messages"
|
||||||
"read:mutes": "View your list of muted users"
|
"read:mutes": "List users which are muted or whose renotes are muted"
|
||||||
"write:mutes": "Edit your list of muted users"
|
"write:mutes": "Mute and unmute users or their renotes"
|
||||||
"write:notes": "Compose or delete notes"
|
"write:notes": "Create and delete notes"
|
||||||
"read:notifications": "View your notifications"
|
"read:notifications": "Read notifications"
|
||||||
"write:notifications": "Manage your notifications"
|
"write:notifications": "Mark notifications as read and create custom notifications"
|
||||||
"read:reactions": "View your reactions"
|
"write:reactions": "Create and delete reactions"
|
||||||
"write:reactions": "Edit your reactions"
|
"write:votes": "Vote in polls"
|
||||||
"write:votes": "Vote on a poll"
|
"read:pages": "List and read pages"
|
||||||
"read:pages": "View your pages"
|
"write:pages": "Create, change and delete pages"
|
||||||
"write:pages": "Edit or delete your pages"
|
"read:page-likes": "List and read page likes"
|
||||||
"read:page-likes": "View your likes on pages"
|
"write:page-likes": "Like and unlike pages"
|
||||||
"write:page-likes": "Edit your likes on pages"
|
"read:user-groups": "List and view joined, owned and invited to groups"
|
||||||
"read:user-groups": "View your user groups"
|
"write:user-groups": "Create, modify, delete, transfer, join and leave groups. Invite and ban others from groups. Accept and reject group invitations."
|
||||||
"write:user-groups": "Edit or delete your user groups"
|
"read:channels": "List and read followed and joined channels"
|
||||||
"read:channels": "View your channels"
|
"write:channels": "Create, modify, follow and unfollow channels"
|
||||||
"write:channels": "Edit your channels"
|
"read:gallery": "List and read gallery posts"
|
||||||
"read:gallery": "View your gallery"
|
"write:gallery": "Create, modify and delete gallery posts"
|
||||||
"write:gallery": "Edit your gallery"
|
"read:gallery-likes": "List and read gallery post likes"
|
||||||
"read:gallery-likes": "View your list of liked gallery posts"
|
"write:gallery-likes": "Like and unlike gallery posts"
|
||||||
"write:gallery-likes": "Edit your list of liked gallery posts"
|
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
||||||
shareAccessAsk: "Are you sure you want to authorize this application to access your\
|
shareAccessAsk: "Are you sure you want to authorize this application to access your\
|
||||||
|
@ -1342,16 +1343,6 @@ _deck:
|
||||||
list: "List"
|
list: "List"
|
||||||
mentions: "Mentions"
|
mentions: "Mentions"
|
||||||
direct: "Direct notes"
|
direct: "Direct notes"
|
||||||
_services:
|
|
||||||
_discord:
|
|
||||||
connected: "Discord: @{username}#{discriminator} connected to FoundKey: @{mkUsername}!"
|
|
||||||
disconnected: "Discord linkage has been removed."
|
|
||||||
_twitter:
|
|
||||||
connected: "Twitter: @{twitterUserName} connected to FoundKey: @{userName}!"
|
|
||||||
disconnected: "Twitter linkage has been removed."
|
|
||||||
_github:
|
|
||||||
connected: "GitHub: @{login} connected to FoundKey: @{userName}!"
|
|
||||||
disconnected: "GitHub linkage has been removed."
|
|
||||||
_translationService:
|
_translationService:
|
||||||
_deepl:
|
_deepl:
|
||||||
authKey: "DeepL Auth Key"
|
authKey: "DeepL Auth Key"
|
||||||
|
|
|
@ -311,9 +311,6 @@ dayX: "Día {day}"
|
||||||
monthX: "Mes {month}"
|
monthX: "Mes {month}"
|
||||||
yearX: "Año {year}"
|
yearX: "Año {year}"
|
||||||
pages: "Páginas"
|
pages: "Páginas"
|
||||||
integration: "Integración"
|
|
||||||
connectService: "Conectar"
|
|
||||||
disconnectService: "Desconectar"
|
|
||||||
enableLocalTimeline: "Habilitar linea de tiempo local"
|
enableLocalTimeline: "Habilitar linea de tiempo local"
|
||||||
enableGlobalTimeline: "Habilitar linea de tiempo global"
|
enableGlobalTimeline: "Habilitar linea de tiempo global"
|
||||||
disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia\
|
disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia\
|
||||||
|
@ -420,7 +417,6 @@ normalPassword: "Buena contraseña"
|
||||||
strongPassword: "Muy buena contraseña"
|
strongPassword: "Muy buena contraseña"
|
||||||
passwordMatched: "Correcto"
|
passwordMatched: "Correcto"
|
||||||
passwordNotMatched: "Las contraseñas no son las mismas"
|
passwordNotMatched: "Las contraseñas no son las mismas"
|
||||||
signinWith: "Inicie sesión con {x}"
|
|
||||||
signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario\
|
signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario\
|
||||||
\ y contraseña correctos."
|
\ y contraseña correctos."
|
||||||
tapSecurityKey: "Toque la clave de seguridad"
|
tapSecurityKey: "Toque la clave de seguridad"
|
||||||
|
|
|
@ -311,9 +311,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Pages"
|
pages: "Pages"
|
||||||
integration: "Intégrations"
|
|
||||||
connectService: "Connexion"
|
|
||||||
disconnectService: "Déconnexion"
|
|
||||||
enableLocalTimeline: "Activer le fil local"
|
enableLocalTimeline: "Activer le fil local"
|
||||||
enableGlobalTimeline: "Activer le fil global"
|
enableGlobalTimeline: "Activer le fil global"
|
||||||
disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s\
|
disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s\
|
||||||
|
@ -423,7 +420,6 @@ normalPassword: "Mot de passe acceptable"
|
||||||
strongPassword: "Mot de passe fort"
|
strongPassword: "Mot de passe fort"
|
||||||
passwordMatched: "Les mots de passe correspondent"
|
passwordMatched: "Les mots de passe correspondent"
|
||||||
passwordNotMatched: "Les mots de passe ne correspondent pas"
|
passwordNotMatched: "Les mots de passe ne correspondent pas"
|
||||||
signinWith: "Se connecter avec {x}"
|
|
||||||
signinFailed: "Échec d’authentification. Veuillez vérifier que votre nom d’utilisateur\
|
signinFailed: "Échec d’authentification. Veuillez vérifier que votre nom d’utilisateur\
|
||||||
\ et mot de passe sont corrects."
|
\ et mot de passe sont corrects."
|
||||||
tapSecurityKey: "Appuyez sur votre clé de sécurité"
|
tapSecurityKey: "Appuyez sur votre clé de sécurité"
|
||||||
|
@ -1331,18 +1327,6 @@ _deck:
|
||||||
list: "Listes"
|
list: "Listes"
|
||||||
mentions: "Mentions"
|
mentions: "Mentions"
|
||||||
direct: "Direct"
|
direct: "Direct"
|
||||||
_services:
|
|
||||||
_discord:
|
|
||||||
connected: '@{username}#{discriminator} sur Discord est connecté à @{mkUsername}
|
|
||||||
sur FoundKey !'
|
|
||||||
disconnected: La liaison avec Discord à été supprimée.
|
|
||||||
_twitter:
|
|
||||||
connected: '@{twitterUserName} sur Twitter est connecté à @{userName} sur FoundKey
|
|
||||||
!'
|
|
||||||
disconnected: La liaison avec Twitter à été supprimée.
|
|
||||||
_github:
|
|
||||||
disconnected: La liaison avec Github à été supprimée.
|
|
||||||
connected: '@{login} sur Github est connecté à @{userName} sur FoundKey !'
|
|
||||||
exportAll: Tout exporter
|
exportAll: Tout exporter
|
||||||
stopActivityDeliveryDescription: L'activité locale ne sera pas envoyé à cette instance.
|
stopActivityDeliveryDescription: L'activité locale ne sera pas envoyé à cette instance.
|
||||||
La réception de l'activité continuera de fonctionner comme avant.
|
La réception de l'activité continuera de fonctionner comme avant.
|
||||||
|
|
|
@ -310,9 +310,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Halaman"
|
pages: "Halaman"
|
||||||
integration: "Integrasi"
|
|
||||||
connectService: "Sambungkan"
|
|
||||||
disconnectService: "Putuskan"
|
|
||||||
enableLocalTimeline: "Nyalakan linimasa lokal"
|
enableLocalTimeline: "Nyalakan linimasa lokal"
|
||||||
enableGlobalTimeline: "Nyalakan linimasa global"
|
enableGlobalTimeline: "Nyalakan linimasa global"
|
||||||
disablingTimelinesInfo: "Admin dan Moderator akan selalu memiliki akses ke semua linimasa\
|
disablingTimelinesInfo: "Admin dan Moderator akan selalu memiliki akses ke semua linimasa\
|
||||||
|
@ -419,7 +416,6 @@ normalPassword: "Kata sandi baik"
|
||||||
strongPassword: "Kata sandi kuat"
|
strongPassword: "Kata sandi kuat"
|
||||||
passwordMatched: "Kata sandi sama"
|
passwordMatched: "Kata sandi sama"
|
||||||
passwordNotMatched: "Kata sandi tidak sama"
|
passwordNotMatched: "Kata sandi tidak sama"
|
||||||
signinWith: "Masuk dengan {x}"
|
|
||||||
signinFailed: "Tidak dapat masuk. Nama pengguna atau kata sandi yang kamu masukkan\
|
signinFailed: "Tidak dapat masuk. Nama pengguna atau kata sandi yang kamu masukkan\
|
||||||
\ salah."
|
\ salah."
|
||||||
tapSecurityKey: "Ketuk kunci keamanan kamu"
|
tapSecurityKey: "Ketuk kunci keamanan kamu"
|
||||||
|
|
|
@ -304,9 +304,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Pagine"
|
pages: "Pagine"
|
||||||
integration: "App collegate"
|
|
||||||
connectService: "Connessione"
|
|
||||||
disconnectService: "Disconnessione "
|
|
||||||
enableLocalTimeline: "Abilita Timeline locale"
|
enableLocalTimeline: "Abilita Timeline locale"
|
||||||
enableGlobalTimeline: "Abilita Timeline federata"
|
enableGlobalTimeline: "Abilita Timeline federata"
|
||||||
disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e\
|
disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e\
|
||||||
|
@ -413,7 +410,6 @@ normalPassword: "Password buona"
|
||||||
strongPassword: "Password forte"
|
strongPassword: "Password forte"
|
||||||
passwordMatched: "Corretta"
|
passwordMatched: "Corretta"
|
||||||
passwordNotMatched: "Le password non corrispondono."
|
passwordNotMatched: "Le password non corrispondono."
|
||||||
signinWith: "Accedi con {x}"
|
|
||||||
signinFailed: "Autenticazione non riuscita. Controlla la tua password e nome utente."
|
signinFailed: "Autenticazione non riuscita. Controlla la tua password e nome utente."
|
||||||
tapSecurityKey: "Premi la chiave di sicurezza"
|
tapSecurityKey: "Premi la chiave di sicurezza"
|
||||||
or: "oppure"
|
or: "oppure"
|
||||||
|
|
|
@ -286,9 +286,6 @@ dayX: "{day}日"
|
||||||
monthX: "{month}月"
|
monthX: "{month}月"
|
||||||
yearX: "{year}年"
|
yearX: "{year}年"
|
||||||
pages: "ページ"
|
pages: "ページ"
|
||||||
integration: "連携"
|
|
||||||
connectService: "接続する"
|
|
||||||
disconnectService: "切断する"
|
|
||||||
enableLocalTimeline: "ローカルタイムラインを有効にする"
|
enableLocalTimeline: "ローカルタイムラインを有効にする"
|
||||||
enableGlobalTimeline: "グローバルタイムラインを有効にする"
|
enableGlobalTimeline: "グローバルタイムラインを有効にする"
|
||||||
disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
|
disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
|
||||||
|
@ -392,7 +389,6 @@ normalPassword: "普通のパスワード"
|
||||||
strongPassword: "強いパスワード"
|
strongPassword: "強いパスワード"
|
||||||
passwordMatched: "一致しました"
|
passwordMatched: "一致しました"
|
||||||
passwordNotMatched: "一致していません"
|
passwordNotMatched: "一致していません"
|
||||||
signinWith: "{x}でログイン"
|
|
||||||
signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||||
tapSecurityKey: "セキュリティキーにタッチ"
|
tapSecurityKey: "セキュリティキーにタッチ"
|
||||||
or: "もしくは"
|
or: "もしくは"
|
||||||
|
@ -1273,13 +1269,3 @@ _deck:
|
||||||
list: "リスト"
|
list: "リスト"
|
||||||
mentions: "あなた宛て"
|
mentions: "あなた宛て"
|
||||||
direct: "ダイレクト"
|
direct: "ダイレクト"
|
||||||
_services:
|
|
||||||
_discord:
|
|
||||||
connected: "Discord: @{username}#{discriminator} を、FoundKey: @{mkUsername} に接続しました!"
|
|
||||||
disconnected: "Discordの連携を解除しました :v:"
|
|
||||||
_twitter:
|
|
||||||
connected: "Twitter: @{twitterUserName} を、FoundKey: @{userName} に接続しました!"
|
|
||||||
disconnected: "Twitterの連携を解除しました :v:"
|
|
||||||
_github:
|
|
||||||
connected: "GitHub: @{login} を、FoundKey: @{userName} に接続しました!"
|
|
||||||
disconnected: "GitHubの連携を解除しました :v:"
|
|
||||||
|
|
|
@ -288,7 +288,6 @@ dayX: "{day}日"
|
||||||
monthX: "{month}月"
|
monthX: "{month}月"
|
||||||
yearX: "{year}年"
|
yearX: "{year}年"
|
||||||
pages: "ページ"
|
pages: "ページ"
|
||||||
integration: "連携"
|
|
||||||
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
|
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
|
||||||
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
|
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
|
||||||
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
|
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
|
||||||
|
@ -391,7 +390,6 @@ normalPassword: "普通のパスワード"
|
||||||
strongPassword: "ええ感じのパスワード"
|
strongPassword: "ええ感じのパスワード"
|
||||||
passwordMatched: "よし!一致や!"
|
passwordMatched: "よし!一致や!"
|
||||||
passwordNotMatched: "一致しとらんで?"
|
passwordNotMatched: "一致しとらんで?"
|
||||||
signinWith: "{x}でログイン"
|
|
||||||
or: "それか"
|
or: "それか"
|
||||||
language: "言語"
|
language: "言語"
|
||||||
uiLanguage: "UIの表示言語"
|
uiLanguage: "UIの表示言語"
|
||||||
|
|
|
@ -39,7 +39,6 @@ userList: "Tibdarin"
|
||||||
securityKey: "Tasarutt n tɣellist"
|
securityKey: "Tasarutt n tɣellist"
|
||||||
securityKeyName: "Isem n tsarutt"
|
securityKeyName: "Isem n tsarutt"
|
||||||
signinRequired: "Ttxil jerred"
|
signinRequired: "Ttxil jerred"
|
||||||
signinWith: "Tuqqna s {x}"
|
|
||||||
tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
|
tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
|
||||||
uiLanguage: "Tutlayt n wegrudem"
|
uiLanguage: "Tutlayt n wegrudem"
|
||||||
plugins: "Izegrar"
|
plugins: "Izegrar"
|
||||||
|
|
|
@ -315,9 +315,6 @@ dayX: "{day}일"
|
||||||
monthX: "{month}월"
|
monthX: "{month}월"
|
||||||
yearX: "{year}년"
|
yearX: "{year}년"
|
||||||
pages: "페이지"
|
pages: "페이지"
|
||||||
integration: "연동"
|
|
||||||
connectService: "계정 연동"
|
|
||||||
disconnectService: "계정 연동 해제"
|
|
||||||
enableLocalTimeline: "로컬 타임라인 활성화"
|
enableLocalTimeline: "로컬 타임라인 활성화"
|
||||||
enableGlobalTimeline: "글로벌 타임라인 활성화"
|
enableGlobalTimeline: "글로벌 타임라인 활성화"
|
||||||
disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
|
disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
|
||||||
|
@ -438,7 +435,6 @@ normalPassword: "좋은 비밀번호"
|
||||||
strongPassword: "강한 비밀번호"
|
strongPassword: "강한 비밀번호"
|
||||||
passwordMatched: "일치합니다"
|
passwordMatched: "일치합니다"
|
||||||
passwordNotMatched: "일치하지 않습니다"
|
passwordNotMatched: "일치하지 않습니다"
|
||||||
signinWith: "{x}로 로그인"
|
|
||||||
signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
|
signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
|
||||||
tapSecurityKey: "보안 키를 터치"
|
tapSecurityKey: "보안 키를 터치"
|
||||||
or: "혹은"
|
or: "혹은"
|
||||||
|
|
|
@ -298,9 +298,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Strony"
|
pages: "Strony"
|
||||||
integration: "Integracja"
|
|
||||||
connectService: "Połącz"
|
|
||||||
disconnectService: "Rozłącz"
|
|
||||||
enableLocalTimeline: "Włącz lokalną oś czasu"
|
enableLocalTimeline: "Włącz lokalną oś czasu"
|
||||||
enableGlobalTimeline: "Włącz globalną oś czasu"
|
enableGlobalTimeline: "Włącz globalną oś czasu"
|
||||||
disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do\
|
disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do\
|
||||||
|
@ -407,7 +404,6 @@ normalPassword: "Dobre hasło"
|
||||||
strongPassword: "Silne hasło"
|
strongPassword: "Silne hasło"
|
||||||
passwordMatched: "Pasuje"
|
passwordMatched: "Pasuje"
|
||||||
passwordNotMatched: "Hasła nie pasują do siebie"
|
passwordNotMatched: "Hasła nie pasują do siebie"
|
||||||
signinWith: "Zaloguj się z {x}"
|
|
||||||
signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są\
|
signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są\
|
||||||
\ nieprawidłowe."
|
\ nieprawidłowe."
|
||||||
tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
|
tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
|
||||||
|
|
|
@ -311,9 +311,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Pagini"
|
pages: "Pagini"
|
||||||
integration: "Integrare"
|
|
||||||
connectService: "Conectează"
|
|
||||||
disconnectService: "Deconectează"
|
|
||||||
enableLocalTimeline: "Activează cronologia locală"
|
enableLocalTimeline: "Activează cronologia locală"
|
||||||
enableGlobalTimeline: "Activeaza cronologia globală"
|
enableGlobalTimeline: "Activeaza cronologia globală"
|
||||||
disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate\
|
disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate\
|
||||||
|
@ -420,7 +417,6 @@ normalPassword: "Parolă medie"
|
||||||
strongPassword: "Parolă puternică"
|
strongPassword: "Parolă puternică"
|
||||||
passwordMatched: "Se potrivește!"
|
passwordMatched: "Se potrivește!"
|
||||||
passwordNotMatched: "Nu se potrivește"
|
passwordNotMatched: "Nu se potrivește"
|
||||||
signinWith: "Autentifică-te cu {x}"
|
|
||||||
signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse\
|
signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse\
|
||||||
\ sunt incorecte."
|
\ sunt incorecte."
|
||||||
tapSecurityKey: "Apasă pe cheia ta de securitate."
|
tapSecurityKey: "Apasă pe cheia ta de securitate."
|
||||||
|
|
|
@ -304,9 +304,6 @@ dayX: "{day} день"
|
||||||
monthX: "{month} месяц"
|
monthX: "{month} месяц"
|
||||||
yearX: "{year} год"
|
yearX: "{year} год"
|
||||||
pages: "Страницы"
|
pages: "Страницы"
|
||||||
integration: "Интеграция"
|
|
||||||
connectService: "Подключиться"
|
|
||||||
disconnectService: "Отключиться"
|
|
||||||
enableLocalTimeline: "Включить локальную ленту"
|
enableLocalTimeline: "Включить локальную ленту"
|
||||||
enableGlobalTimeline: "Включить глобальную ленту"
|
enableGlobalTimeline: "Включить глобальную ленту"
|
||||||
disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам,\
|
disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам,\
|
||||||
|
@ -415,7 +412,6 @@ normalPassword: "Годный пароль"
|
||||||
strongPassword: "Надёжный пароль"
|
strongPassword: "Надёжный пароль"
|
||||||
passwordMatched: "Совпали"
|
passwordMatched: "Совпали"
|
||||||
passwordNotMatched: "Не совпадают"
|
passwordNotMatched: "Не совпадают"
|
||||||
signinWith: "Использовать {x} для входа"
|
|
||||||
signinFailed: "Невозможно войти в систему. Введенное вами имя пользователя или пароль\
|
signinFailed: "Невозможно войти в систему. Введенное вами имя пользователя или пароль\
|
||||||
\ неверны."
|
\ неверны."
|
||||||
tapSecurityKey: "Нажмите на свой электронный ключ"
|
tapSecurityKey: "Нажмите на свой электронный ключ"
|
||||||
|
|
|
@ -305,9 +305,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Stránky"
|
pages: "Stránky"
|
||||||
integration: "Integrácia"
|
|
||||||
connectService: "Pripojiť"
|
|
||||||
disconnectService: "Odpojiť"
|
|
||||||
enableLocalTimeline: "Povoliť lokálnu časovú os"
|
enableLocalTimeline: "Povoliť lokálnu časovú os"
|
||||||
enableGlobalTimeline: "Povoliť globálnu časovú os"
|
enableGlobalTimeline: "Povoliť globálnu časovú os"
|
||||||
disablingTimelinesInfo: "Administrátori a moderátori majú vždy prístup ku všetkým\
|
disablingTimelinesInfo: "Administrátori a moderátori majú vždy prístup ku všetkým\
|
||||||
|
@ -414,7 +411,6 @@ normalPassword: "Dobré heslo"
|
||||||
strongPassword: "Silné heslo"
|
strongPassword: "Silné heslo"
|
||||||
passwordMatched: "Heslá sú rovnaké"
|
passwordMatched: "Heslá sú rovnaké"
|
||||||
passwordNotMatched: "Heslá nie sú rovnaké"
|
passwordNotMatched: "Heslá nie sú rovnaké"
|
||||||
signinWith: "Prihlásiť sa použitím {x}"
|
|
||||||
signinFailed: "Nedá sa prihlásiť. Skontrolujte prosím meno používateľa a heslo."
|
signinFailed: "Nedá sa prihlásiť. Skontrolujte prosím meno používateľa a heslo."
|
||||||
tapSecurityKey: "Ťuknite na bezpečnostný kľúč"
|
tapSecurityKey: "Ťuknite na bezpečnostný kľúč"
|
||||||
or: "Alebo"
|
or: "Alebo"
|
||||||
|
|
|
@ -305,9 +305,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Сторінки"
|
pages: "Сторінки"
|
||||||
integration: "Інтеграція"
|
|
||||||
connectService: "Під’єднати"
|
|
||||||
disconnectService: "Відключитися"
|
|
||||||
enableLocalTimeline: "Увімкнути локальну стрічку"
|
enableLocalTimeline: "Увімкнути локальну стрічку"
|
||||||
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
||||||
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх\
|
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх\
|
||||||
|
@ -414,7 +411,6 @@ normalPassword: "Достатній пароль"
|
||||||
strongPassword: "Міцний пароль"
|
strongPassword: "Міцний пароль"
|
||||||
passwordMatched: "Все вірно"
|
passwordMatched: "Все вірно"
|
||||||
passwordNotMatched: "Паролі не співпадають"
|
passwordNotMatched: "Паролі не співпадають"
|
||||||
signinWith: "Увійти за допомогою {x}"
|
|
||||||
signinFailed: "Не вдалося увійти. Введені ім’я користувача або пароль неправильнi."
|
signinFailed: "Не вдалося увійти. Введені ім’я користувача або пароль неправильнi."
|
||||||
tapSecurityKey: "Торкніться ключа безпеки"
|
tapSecurityKey: "Торкніться ключа безпеки"
|
||||||
or: "або"
|
or: "або"
|
||||||
|
|
|
@ -305,9 +305,6 @@ dayX: "{day}"
|
||||||
monthX: "{month}"
|
monthX: "{month}"
|
||||||
yearX: "{year}"
|
yearX: "{year}"
|
||||||
pages: "Trang"
|
pages: "Trang"
|
||||||
integration: "Tương tác"
|
|
||||||
connectService: "Kết nối"
|
|
||||||
disconnectService: "Ngắt kết nối"
|
|
||||||
enableLocalTimeline: "Bật bảng tin máy chủ"
|
enableLocalTimeline: "Bật bảng tin máy chủ"
|
||||||
enableGlobalTimeline: "Bật bảng tin liên hợp"
|
enableGlobalTimeline: "Bật bảng tin liên hợp"
|
||||||
disablingTimelinesInfo: "Quản trị viên và Kiểm duyệt viên luôn có quyền truy cập mọi\
|
disablingTimelinesInfo: "Quản trị viên và Kiểm duyệt viên luôn có quyền truy cập mọi\
|
||||||
|
@ -415,7 +412,6 @@ normalPassword: "Mật khẩu tạm được"
|
||||||
strongPassword: "Mật khẩu mạnh"
|
strongPassword: "Mật khẩu mạnh"
|
||||||
passwordMatched: "Trùng khớp"
|
passwordMatched: "Trùng khớp"
|
||||||
passwordNotMatched: "Không trùng khớp"
|
passwordNotMatched: "Không trùng khớp"
|
||||||
signinWith: "Đăng nhập bằng {x}"
|
|
||||||
signinFailed: "Không thể đăng nhập. Vui lòng kiểm tra tên người dùng và mật khẩu của\
|
signinFailed: "Không thể đăng nhập. Vui lòng kiểm tra tên người dùng và mật khẩu của\
|
||||||
\ bạn."
|
\ bạn."
|
||||||
tapSecurityKey: "Nhấn mã bảo mật của bạn"
|
tapSecurityKey: "Nhấn mã bảo mật của bạn"
|
||||||
|
|
|
@ -284,9 +284,6 @@ dayX: "{day}日"
|
||||||
monthX: "{month}月"
|
monthX: "{month}月"
|
||||||
yearX: "{year}年"
|
yearX: "{year}年"
|
||||||
pages: "页面"
|
pages: "页面"
|
||||||
integration: "关联"
|
|
||||||
connectService: "连接"
|
|
||||||
disconnectService: "断开连接"
|
|
||||||
enableLocalTimeline: "启用本地时间线功能"
|
enableLocalTimeline: "启用本地时间线功能"
|
||||||
enableGlobalTimeline: "启用全局时间线"
|
enableGlobalTimeline: "启用全局时间线"
|
||||||
disablingTimelinesInfo: "即使时间线功能被禁用,出于方便,管理员和数据图表也可以继续使用。"
|
disablingTimelinesInfo: "即使时间线功能被禁用,出于方便,管理员和数据图表也可以继续使用。"
|
||||||
|
@ -390,7 +387,6 @@ normalPassword: "密码强度:中等"
|
||||||
strongPassword: "密码强度:强"
|
strongPassword: "密码强度:强"
|
||||||
passwordMatched: "密码一致"
|
passwordMatched: "密码一致"
|
||||||
passwordNotMatched: "密码不一致"
|
passwordNotMatched: "密码不一致"
|
||||||
signinWith: "以{x}登录"
|
|
||||||
signinFailed: "无法登录,请检查您的用户名和密码是否正确。"
|
signinFailed: "无法登录,请检查您的用户名和密码是否正确。"
|
||||||
tapSecurityKey: "轻触硬件安全密钥"
|
tapSecurityKey: "轻触硬件安全密钥"
|
||||||
or: "或者"
|
or: "或者"
|
||||||
|
|
|
@ -284,9 +284,6 @@ dayX: "{day}日"
|
||||||
monthX: "{month}月"
|
monthX: "{month}月"
|
||||||
yearX: "{year}年"
|
yearX: "{year}年"
|
||||||
pages: "頁面"
|
pages: "頁面"
|
||||||
integration: "整合"
|
|
||||||
connectService: "己連結"
|
|
||||||
disconnectService: "己斷開 "
|
|
||||||
enableLocalTimeline: "開啟本地時間軸"
|
enableLocalTimeline: "開啟本地時間軸"
|
||||||
enableGlobalTimeline: "啟用公開時間軸"
|
enableGlobalTimeline: "啟用公開時間軸"
|
||||||
disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
|
disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
|
||||||
|
@ -390,7 +387,6 @@ normalPassword: "密碼強度普通"
|
||||||
strongPassword: "密碼強度高"
|
strongPassword: "密碼強度高"
|
||||||
passwordMatched: "密碼一致"
|
passwordMatched: "密碼一致"
|
||||||
passwordNotMatched: "密碼不一致"
|
passwordNotMatched: "密碼不一致"
|
||||||
signinWith: "以{x}登錄"
|
|
||||||
signinFailed: "登入失敗。 請檢查使用者名稱和密碼。"
|
signinFailed: "登入失敗。 請檢查使用者名稱和密碼。"
|
||||||
tapSecurityKey: "點擊安全密鑰"
|
tapSecurityKey: "點擊安全密鑰"
|
||||||
or: "或者"
|
or: "或者"
|
||||||
|
|
10
package.json
|
@ -18,7 +18,7 @@
|
||||||
"migrateandstart": "yarn migrate && yarn start",
|
"migrateandstart": "yarn migrate && yarn start",
|
||||||
"gulp": "gulp build",
|
"gulp": "gulp build",
|
||||||
"watch": "yarn dev",
|
"watch": "yarn dev",
|
||||||
"dev": "node ./scripts/dev.js",
|
"dev": "node ./scripts/dev.mjs",
|
||||||
"lint": "yarn workspaces foreach run lint",
|
"lint": "yarn workspaces foreach run lint",
|
||||||
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
"mocha": "yarn workspace backend run mocha",
|
"mocha": "yarn workspace backend run mocha",
|
||||||
"test": "yarn mocha",
|
"test": "yarn mocha",
|
||||||
"format": "gulp format",
|
"format": "gulp format",
|
||||||
"clean": "node ./scripts/clean.js",
|
"clean": "node ./scripts/clean.mjs",
|
||||||
"clean-all": "node ./scripts/clean-all.js",
|
"clean-all": "node ./scripts/clean-all.mjs",
|
||||||
"cleanall": "yarn clean-all"
|
"cleanall": "yarn clean-all"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
@ -46,11 +46,11 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/gulp": "4.0.9",
|
"@types/gulp": "4.0.9",
|
||||||
"@types/gulp-rename": "2.0.1",
|
"@types/gulp-rename": "2.0.1",
|
||||||
"@typescript-eslint/parser": "^5.44.0",
|
"@typescript-eslint/parser": "^5.46.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "10.3.0",
|
"cypress": "10.3.0",
|
||||||
"start-server-and-test": "1.14.0",
|
"start-server-and-test": "1.14.0",
|
||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.4"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@3.3.0"
|
"packageManager": "yarn@3.3.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
export class tokenPermissions1667653936442 {
|
||||||
|
name = 'tokenPermissions1667653936442'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
// Carry over the permissions from the app for tokens that have an associated app.
|
||||||
|
await queryRunner.query(`UPDATE "access_token" SET permission = (SELECT permission FROM "app" WHERE "app"."id" = "access_token"."appId") WHERE "appId" IS NOT NULL AND CARDINALITY("permission") = 0`);
|
||||||
|
// The permission column should now always be set explicitly, so the default is not needed any more.
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "permission" DROP DEFAULT`);
|
||||||
|
// Drop all currently running authorization sessions. Already created tokens remain untouched.
|
||||||
|
// If you were registering an app just before upgrade started, try again later. ¯\_(ツ)_/¯
|
||||||
|
await queryRunner.query(`TRUNCATE TABLE "auth_session"`);
|
||||||
|
// Refactor scheme to allow multiple access tokens per app.
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" DROP CONSTRAINT "FK_c072b729d71697f959bde66ade0"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" RENAME COLUMN "userId" TO "accessTokenId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" ADD CONSTRAINT "UQ_8e001e5a101c6dca37df1a76d66" UNIQUE ("accessTokenId")`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" ADD CONSTRAINT "FK_8e001e5a101c6dca37df1a76d66" FOREIGN KEY ("accessTokenId") REFERENCES "access_token"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
// Drop all currently running authorization sessions. Already created tokens remain untouched.
|
||||||
|
// If you were registering an app just before downgrade started, try again later. ¯\_(ツ)_/¯
|
||||||
|
await queryRunner.query(`TRUNCATE TABLE "auth_session"`);
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" DROP CONSTRAINT "FK_8e001e5a101c6dca37df1a76d66"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" DROP CONSTRAINT "UQ_8e001e5a101c6dca37df1a76d66"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "permission" DROP DEFAULT`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" RENAME COLUMN "accessTokenId" TO "userId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" ADD CONSTRAINT "FK_c072b729d71697f959bde66ade0" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "permission" SET DEFAULT '{}'::varchar[]`);
|
||||||
|
await queryRunner.query(`UPDATE "access_token" SET permission = '{}'::varchar[] WHERE "appId" IS NOT NULL`);
|
||||||
|
}
|
||||||
|
}
|
12
packages/backend/migration/1667738304733-pkce.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export class pkce1667738304733 {
|
||||||
|
name = 'pkce1667738304733'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" ADD "pkceChallenge" text`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "auth_session"."pkceChallenge" IS 'PKCE code_challenge value, if provided (OAuth only)'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "auth_session" DROP COLUMN "pkceChallenge"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
export class removeIntegrations1670359028055 {
|
||||||
|
name = 'removeIntegrations1670359028055'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableTwitterIntegration"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "twitterConsumerKey"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "twitterConsumerSecret"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableGithubIntegration"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "githubClientId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "githubClientSecret"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableDiscordIntegration"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "discordClientId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "discordClientSecret"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "integrations"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "integrations" jsonb NOT NULL DEFAULT '{}'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "discordClientSecret" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "discordClientId" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "enableDiscordIntegration" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "githubClientSecret" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "githubClientId" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "enableGithubIntegration" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "twitterConsumerSecret" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "twitterConsumerKey" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "enableTwitterIntegration" boolean NOT NULL DEFAULT false`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
|
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
|
||||||
"watch": "node watch.mjs",
|
"watch": "node watch.mjs",
|
||||||
"lint": "eslint src --ext .ts",
|
"lint": "tsc --noEmit && eslint src --ext .ts",
|
||||||
"mocha": "cross-env NODE_ENV=test TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
|
"mocha": "cross-env NODE_ENV=test TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
|
||||||
"migrate": "npx typeorm migration:run -d ormconfig.js",
|
"migrate": "npx typeorm migration:run -d ormconfig.js",
|
||||||
"start": "node --experimental-json-modules ./built/index.js",
|
"start": "node --experimental-json-modules ./built/index.js",
|
||||||
|
@ -29,7 +29,6 @@
|
||||||
"ajv": "8.11.0",
|
"ajv": "8.11.0",
|
||||||
"archiver": "5.3.1",
|
"archiver": "5.3.1",
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
"autwh": "0.1.0",
|
|
||||||
"aws-sdk": "2.1165.0",
|
"aws-sdk": "2.1165.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"blurhash": "1.1.5",
|
"blurhash": "1.1.5",
|
||||||
|
@ -92,7 +91,6 @@
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
"require-all": "3.0.0",
|
"require-all": "3.0.0",
|
||||||
"rndstr": "1.0.0",
|
|
||||||
"rss-parser": "3.12.0",
|
"rss-parser": "3.12.0",
|
||||||
"sanitize-html": "2.7.0",
|
"sanitize-html": "2.7.0",
|
||||||
"semver": "7.3.7",
|
"semver": "7.3.7",
|
||||||
|
@ -124,6 +122,7 @@
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
"@types/bull": "3.15.8",
|
"@types/bull": "3.15.8",
|
||||||
"@types/cbor": "6.0.0",
|
"@types/cbor": "6.0.0",
|
||||||
|
"@types/color-convert": "^2.0.0",
|
||||||
"@types/escape-regexp": "0.0.1",
|
"@types/escape-regexp": "0.0.1",
|
||||||
"@types/fluent-ffmpeg": "2.1.20",
|
"@types/fluent-ffmpeg": "2.1.20",
|
||||||
"@types/is-url": "1.2.30",
|
"@types/is-url": "1.2.30",
|
||||||
|
@ -146,7 +145,6 @@
|
||||||
"@types/node": "18.7.16",
|
"@types/node": "18.7.16",
|
||||||
"@types/node-fetch": "3.0.3",
|
"@types/node-fetch": "3.0.3",
|
||||||
"@types/nodemailer": "6.4.5",
|
"@types/nodemailer": "6.4.5",
|
||||||
"@types/oauth": "^0.9.1",
|
|
||||||
"@types/pg": "^8.6.5",
|
"@types/pg": "^8.6.5",
|
||||||
"@types/pug": "2.0.6",
|
"@types/pug": "2.0.6",
|
||||||
"@types/punycode": "2.1.0",
|
"@types/punycode": "2.1.0",
|
||||||
|
@ -161,20 +159,21 @@
|
||||||
"@types/sinon": "^10.0.13",
|
"@types/sinon": "^10.0.13",
|
||||||
"@types/sinonjs__fake-timers": "8.1.2",
|
"@types/sinonjs__fake-timers": "8.1.2",
|
||||||
"@types/speakeasy": "2.0.7",
|
"@types/speakeasy": "2.0.7",
|
||||||
|
"@types/syslog-pro": "^1.0.0",
|
||||||
"@types/tinycolor2": "1.4.3",
|
"@types/tinycolor2": "1.4.3",
|
||||||
"@types/tmp": "0.2.3",
|
"@types/tmp": "0.2.3",
|
||||||
"@types/uuid": "8.3.4",
|
"@types/uuid": "8.3.4",
|
||||||
"@types/web-push": "3.3.2",
|
"@types/web-push": "3.3.2",
|
||||||
"@types/websocket": "1.0.5",
|
"@types/websocket": "1.0.5",
|
||||||
"@types/ws": "8.5.3",
|
"@types/ws": "8.5.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
||||||
"@typescript-eslint/parser": "^5.44.0",
|
"@typescript-eslint/parser": "^5.46.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.29.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"execa": "6.1.0",
|
"execa": "6.1.0",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"sinon": "^14.0.2",
|
"sinon": "^14.0.2",
|
||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ const ev = new Xev();
|
||||||
/**
|
/**
|
||||||
* Init process
|
* Init process
|
||||||
*/
|
*/
|
||||||
export default async function(): Promise<void> {
|
export async function boot(): Promise<void> {
|
||||||
process.title = `FoundKey (${cluster.isPrimary ? 'master' : 'worker'})`;
|
process.title = `FoundKey (${cluster.isPrimary ? 'master' : 'worker'})`;
|
||||||
|
|
||||||
if (cluster.isPrimary || envOption.disableClustering) {
|
if (cluster.isPrimary || envOption.disableClustering) {
|
||||||
|
|
|
@ -153,7 +153,7 @@ async function spawnWorkers(clusterLimits: Required<Config['clusterLimits']>): P
|
||||||
|
|
||||||
bootLogger.info(`Starting ${total} workers...`);
|
bootLogger.info(`Starting ${total} workers...`);
|
||||||
await Promise.all(workers.map(mode => spawnWorker(mode)));
|
await Promise.all(workers.map(mode => spawnWorker(mode)));
|
||||||
bootLogger.succ(`All workers started`);
|
bootLogger.succ('All workers started');
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnWorker(mode: 'web' | 'queue'): Promise<void> {
|
function spawnWorker(mode: 'web' | 'queue'): Promise<void> {
|
||||||
|
|
|
@ -38,6 +38,12 @@ export default function load(): Config {
|
||||||
|
|
||||||
config.port = config.port || parseInt(process.env.PORT || '', 10);
|
config.port = config.port || parseInt(process.env.PORT || '', 10);
|
||||||
|
|
||||||
|
config.images = Object.assign({
|
||||||
|
info: '/twemoji/1f440.svg',
|
||||||
|
notFound: '/twemoji/2049.svg',
|
||||||
|
error: '/twemoji/1f480.svg',
|
||||||
|
}, config.images ?? {});
|
||||||
|
|
||||||
if (!config.maxNoteTextLength) config.maxNoteTextLength = 3000;
|
if (!config.maxNoteTextLength) config.maxNoteTextLength = 3000;
|
||||||
|
|
||||||
mixin.version = meta.version;
|
mixin.version = meta.version;
|
||||||
|
|
|
@ -59,7 +59,7 @@ export type Source = {
|
||||||
deliverJobMaxAttempts?: number;
|
deliverJobMaxAttempts?: number;
|
||||||
inboxJobMaxAttempts?: number;
|
inboxJobMaxAttempts?: number;
|
||||||
|
|
||||||
syslog: {
|
syslog?: {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
};
|
};
|
||||||
|
@ -67,6 +67,12 @@ export type Source = {
|
||||||
mediaProxy?: string;
|
mediaProxy?: string;
|
||||||
proxyRemoteFiles?: boolean;
|
proxyRemoteFiles?: boolean;
|
||||||
internalStoragePath?: string;
|
internalStoragePath?: string;
|
||||||
|
|
||||||
|
images?: {
|
||||||
|
info?: string;
|
||||||
|
notFound?: string;
|
||||||
|
error?: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// https://github.com/typeorm/typeorm/issues/2400
|
// https://github.com/typeorm/typeorm/issues/2400
|
||||||
import pg from 'pg';
|
import pg from 'pg';
|
||||||
import { SECOND } from '@/const.js';
|
|
||||||
|
|
||||||
pg.types.setTypeParser(20, Number);
|
pg.types.setTypeParser(20, Number);
|
||||||
|
|
||||||
|
@ -8,6 +7,7 @@ import { Logger, DataSource } from 'typeorm';
|
||||||
import * as highlight from 'cli-highlight';
|
import * as highlight from 'cli-highlight';
|
||||||
import config from '@/config/index.js';
|
import config from '@/config/index.js';
|
||||||
|
|
||||||
|
import { SECOND } from '@/const.js';
|
||||||
import { User } from '@/models/entities/user.js';
|
import { User } from '@/models/entities/user.js';
|
||||||
import { DriveFile } from '@/models/entities/drive-file.js';
|
import { DriveFile } from '@/models/entities/drive-file.js';
|
||||||
import { DriveFolder } from '@/models/entities/drive-folder.js';
|
import { DriveFolder } from '@/models/entities/drive-folder.js';
|
||||||
|
@ -78,33 +78,33 @@ import { redisClient } from './redis.js';
|
||||||
const sqlLogger = dbLogger.createSubLogger('sql', 'gray', false);
|
const sqlLogger = dbLogger.createSubLogger('sql', 'gray', false);
|
||||||
|
|
||||||
class MyCustomLogger implements Logger {
|
class MyCustomLogger implements Logger {
|
||||||
private highlight(sql: string) {
|
private highlight(sql: string): string {
|
||||||
return highlight.highlight(sql, {
|
return highlight.highlight(sql, {
|
||||||
language: 'sql', ignoreIllegals: true,
|
language: 'sql', ignoreIllegals: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public logQuery(query: string, parameters?: any[]) {
|
public logQuery(query: string): void {
|
||||||
sqlLogger.info(this.highlight(query).substring(0, 100));
|
sqlLogger.info(this.highlight(query).substring(0, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
public logQueryError(error: string, query: string, parameters?: any[]) {
|
public logQueryError(error: string, query: string): void {
|
||||||
sqlLogger.error(this.highlight(query));
|
sqlLogger.error(this.highlight(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
public logQuerySlow(time: number, query: string, parameters?: any[]) {
|
public logQuerySlow(time: number, query: string): void {
|
||||||
sqlLogger.warn(this.highlight(query));
|
sqlLogger.warn(this.highlight(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
public logSchemaBuild(message: string) {
|
public logSchemaBuild(message: string): void {
|
||||||
sqlLogger.info(message);
|
sqlLogger.info(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public log(message: string) {
|
public log(message: string): void {
|
||||||
sqlLogger.info(message);
|
sqlLogger.info(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public logMigration(message: string) {
|
public logMigration(message: string): void {
|
||||||
sqlLogger.info(message);
|
sqlLogger.info(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
import boot from '@/boot/index.js';
|
import { boot } from '@/boot/index.js';
|
||||||
|
|
||||||
Error.stackTraceLimit = Infinity;
|
Error.stackTraceLimit = Infinity;
|
||||||
EventEmitter.defaultMaxListeners = 128;
|
EventEmitter.defaultMaxListeners = 128;
|
||||||
|
|
|
@ -7,6 +7,16 @@ const treeAdapter = parse5.defaultTreeAdapter;
|
||||||
const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
|
const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
|
||||||
const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/;
|
const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/;
|
||||||
|
|
||||||
|
function getAttr(node: TreeAdapter.Node, attr: string): string {
|
||||||
|
return node.attrs.find(({ name }) => name === attr)?.value;
|
||||||
|
}
|
||||||
|
function attrHas(node: TreeAdapter.Node, attr: string, value: string): boolean {
|
||||||
|
const attrValue = getAttr(node, attr);
|
||||||
|
if (!attrValue) return false;
|
||||||
|
|
||||||
|
return new RegExp('\\b' + value + '\\b').test(attrValue);
|
||||||
|
}
|
||||||
|
|
||||||
export function fromHtml(html: string, quoteUri?: string | null): string {
|
export function fromHtml(html: string, quoteUri?: string | null): string {
|
||||||
const dom = parse5.parseFragment(
|
const dom = parse5.parseFragment(
|
||||||
// some AP servers like Pixelfed use br tags as well as newlines
|
// some AP servers like Pixelfed use br tags as well as newlines
|
||||||
|
@ -59,19 +69,18 @@ export function fromHtml(html: string, quoteUri?: string | null): string {
|
||||||
case 'a':
|
case 'a':
|
||||||
{
|
{
|
||||||
const txt = getText(node);
|
const txt = getText(node);
|
||||||
const rel = node.attrs.find(x => x.name === 'rel');
|
const href = getAttr(node, 'href');
|
||||||
const href = node.attrs.find(x => x.name === 'href');
|
|
||||||
|
|
||||||
// hashtags
|
// hashtags
|
||||||
if (txt.startsWith('#') && href && /\btag\b/.test(rel?.value)) {
|
if (txt.startsWith('#') && href && (attrHas(node, 'rel', 'tag') || attrHas(node, 'class', 'hashtag'))) {
|
||||||
text += txt;
|
text += txt;
|
||||||
// mentions
|
// mentions
|
||||||
} else if (txt.startsWith('@') && !(rel && rel.value.match(/^me /))) {
|
} else if (txt.startsWith('@') && !attrHas(node, 'rel', 'me')) {
|
||||||
const part = txt.split('@');
|
const part = txt.split('@');
|
||||||
|
|
||||||
if (part.length === 2 && href) {
|
if (part.length === 2 && href) {
|
||||||
// restore the host name part
|
// restore the host name part
|
||||||
const acct = `${txt}@${(new URL(href.value)).hostname}`;
|
const acct = `${txt}@${(new URL(href)).hostname}`;
|
||||||
text += acct;
|
text += acct;
|
||||||
} else if (part.length === 3) {
|
} else if (part.length === 3) {
|
||||||
text += txt;
|
text += txt;
|
||||||
|
@ -85,17 +94,17 @@ export function fromHtml(html: string, quoteUri?: string | null): string {
|
||||||
if (!href) {
|
if (!href) {
|
||||||
return txt;
|
return txt;
|
||||||
}
|
}
|
||||||
if (!txt || txt === href.value) { // #6383: Missing text node
|
if (!txt || txt === href) { // #6383: Missing text node
|
||||||
if (href.value.match(urlRegexFull)) {
|
if (href.match(urlRegexFull)) {
|
||||||
return href.value;
|
return href;
|
||||||
} else {
|
} else {
|
||||||
return `<${href.value}>`;
|
return `<${href}>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (href.value.match(urlRegex) && !href.value.match(urlRegexFull)) {
|
if (href.match(urlRegex) && !href.match(urlRegexFull)) {
|
||||||
return `[${txt}](<${href.value}>)`; // #6846
|
return `[${txt}](<${href}>)`; // #6846
|
||||||
} else {
|
} else {
|
||||||
return `[${txt}](${href.value})`;
|
return `[${txt}](${href})`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,8 +213,7 @@ export function fromHtml(html: string, quoteUri?: string | null): string {
|
||||||
|
|
||||||
case 'span':
|
case 'span':
|
||||||
{
|
{
|
||||||
const nodeClass = node.attrs.find(({ name }) => name === 'class')?.value;
|
if (attrHas(node, 'class', 'quote-inline') && quoteUri && getText(node).trim() === `RE: ${quoteUri}`) {
|
||||||
if (/\bquote-inline\b/.test(nodeClass) && quoteUri && getText(node).trim() === `RE: ${quoteUri}`) {
|
|
||||||
// embedded quote thingy for backwards compatibility, don't show it
|
// embedded quote thingy for backwards compatibility, don't show it
|
||||||
} else {
|
} else {
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export class Cache<T> {
|
export class Cache<T> {
|
||||||
public cache: Map<string | null, { date: number; value: T; }>;
|
public cache: Map<string, { date: number; value: T; }>;
|
||||||
private lifetime: number;
|
private lifetime: number;
|
||||||
public fetcher: (key: string | null) => Promise<T | undefined>;
|
public fetcher: (key: string) => Promise<T | undefined>;
|
||||||
|
|
||||||
constructor(lifetime: number, fetcher: Cache<T>['fetcher']) {
|
constructor(lifetime: number, fetcher: Cache<T>['fetcher']) {
|
||||||
this.cache = new Map();
|
this.cache = new Map();
|
||||||
|
@ -9,14 +9,14 @@ export class Cache<T> {
|
||||||
this.fetcher = fetcher;
|
this.fetcher = fetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public set(key: string | null, value: T): void {
|
public set(key: string, value: T): void {
|
||||||
this.cache.set(key, {
|
this.cache.set(key, {
|
||||||
date: Date.now(),
|
date: Date.now(),
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get(key: string | null): T | undefined {
|
public get(key: string): T | undefined {
|
||||||
const cached = this.cache.get(key);
|
const cached = this.cache.get(key);
|
||||||
if (cached == null) return undefined;
|
if (cached == null) return undefined;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ export class Cache<T> {
|
||||||
return cached.value;
|
return cached.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public delete(key: string | null): void {
|
public delete(key: string): void {
|
||||||
this.cache.delete(key);
|
this.cache.delete(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ export class Cache<T> {
|
||||||
* run to get the value. If the fetcher returns undefined, it is
|
* run to get the value. If the fetcher returns undefined, it is
|
||||||
* returned but not cached.
|
* returned but not cached.
|
||||||
*/
|
*/
|
||||||
public async fetch(key: string | null): Promise<T | undefined> {
|
public async fetch(key: string): Promise<T | undefined> {
|
||||||
const cached = this.get(key);
|
const cached = this.get(key);
|
||||||
if (cached !== undefined) {
|
if (cached !== undefined) {
|
||||||
return cached;
|
return cached;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import * as crypto from 'node:crypto';
|
import * as crypto from 'node:crypto';
|
||||||
|
|
||||||
const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||||
const LU_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
const LU_CHARS = L_CHARS + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
|
||||||
export function secureRndstr(length = 32, useLU = true): string {
|
export function secureRndstrCustom(length = 32, chars: string): string {
|
||||||
const chars = useLU ? LU_CHARS : L_CHARS;
|
|
||||||
const chars_len = chars.length;
|
const chars_len = chars.length;
|
||||||
|
|
||||||
let str = '';
|
let str = '';
|
||||||
|
@ -19,3 +18,8 @@ export function secureRndstr(length = 32, useLU = true): string {
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function secureRndstr(length = 32, useLU = true): string {
|
||||||
|
const chars = useLU ? LU_CHARS : L_CHARS;
|
||||||
|
return secureRndstrCustom(length, chars);
|
||||||
|
}
|
||||||
|
|
16
packages/backend/src/misc/should-block-instance.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||||
|
import { Instance } from '@/models/entities/instance.js';
|
||||||
|
import { Meta } from '@/models/entities/meta.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a specific host (punycoded) should be blocked.
|
||||||
|
*
|
||||||
|
* @param host punycoded instance host
|
||||||
|
* @param meta a Promise contatining the information from the meta table (optional)
|
||||||
|
* @returns whether the given host should be blocked
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function shouldBlockInstance(host: Instance['host'], meta: Promise<Meta> = fetchMeta()): Promise<boolean> {
|
||||||
|
const { blockedHosts } = await meta;
|
||||||
|
return blockedHosts.some(blockedHost => host === blockedHost || host.endsWith('.' + blockedHost));
|
||||||
|
}
|
|
@ -2,39 +2,12 @@ import { db } from '@/db/postgre.js';
|
||||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||||
import { Instance } from '@/models/entities/instance.js';
|
import { Instance } from '@/models/entities/instance.js';
|
||||||
import { DAY } from '@/const.js';
|
import { DAY } from '@/const.js';
|
||||||
import { Meta } from '@/models/entities/meta.js';
|
import { shouldBlockInstance } from '@/misc/should-block-instance.js';
|
||||||
|
|
||||||
// Threshold from last contact after which an instance will be considered
|
// Threshold from last contact after which an instance will be considered
|
||||||
// "dead" and should no longer get activities delivered to it.
|
// "dead" and should no longer get activities delivered to it.
|
||||||
const deadThreshold = 7 * DAY;
|
const deadThreshold = 7 * DAY;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a given host matches a wildcard pattern.
|
|
||||||
* @param host punycoded instance host
|
|
||||||
* @param pattern wildcard pattern containing a punycoded instance host
|
|
||||||
* @returns whether the post matches the pattern
|
|
||||||
*/
|
|
||||||
function matchHost(host: Instance['host'], pattern: string): boolean {
|
|
||||||
// Escape all of the regex special characters. Pattern from:
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
|
||||||
const escape = (str: string): string => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
||||||
const re = new RegExp('^' + pattern.split('*').map(escape).join('.*') + '$');
|
|
||||||
|
|
||||||
return re.test(host);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a specific host (punycoded) should be blocked.
|
|
||||||
*
|
|
||||||
* @param host punycoded instance host
|
|
||||||
* @param meta a Promise contatining the information from the meta table (oprional)
|
|
||||||
* @returns whether the given host should be blocked
|
|
||||||
*/
|
|
||||||
export async function shouldBlockInstance(host: string, meta: Promise<Meta> = fetchMeta()): Promise<boolean> {
|
|
||||||
const { blockedHosts } = await meta;
|
|
||||||
return blockedHosts.some(blockedHost => matchHost(host, blockedHost));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the subset of hosts which should be skipped.
|
* Returns the subset of hosts which should be skipped.
|
||||||
*
|
*
|
||||||
|
@ -62,7 +35,7 @@ export async function skippedInstances(hosts: Array<Instance['host']>): Promise<
|
||||||
hosts.filter(host => !skipped.includes(host) && !host.includes(',')).join(','),
|
hosts.filter(host => !skipped.includes(host) && !host.includes(',')).join(','),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.then(res => res.map(row => row.host)),
|
.then((res: Instance[]) => res.map(row => row.host)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class AbuseUserReport {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public targetUserId: User['id'];
|
public targetUserId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -27,7 +27,7 @@ export class AbuseUserReport {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public reporterId: User['id'];
|
public reporterId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -39,7 +39,7 @@ export class AbuseUserReport {
|
||||||
})
|
})
|
||||||
public assigneeId: User['id'] | null;
|
public assigneeId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -41,7 +41,7 @@ export class AccessToken {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -53,7 +53,7 @@ export class AccessToken {
|
||||||
})
|
})
|
||||||
public appId: App['id'] | null;
|
public appId: App['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => App, {
|
@ManyToOne(() => App, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class AnnouncementRead {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -28,7 +28,7 @@ export class AnnouncementRead {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public announcementId: Announcement['id'];
|
public announcementId: Announcement['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Announcement, {
|
@ManyToOne(() => Announcement, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class AntennaNote {
|
||||||
})
|
})
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -29,7 +29,7 @@ export class AntennaNote {
|
||||||
})
|
})
|
||||||
public antennaId: Antenna['id'];
|
public antennaId: Antenna['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Antenna, {
|
@ManyToOne(() => Antenna, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class Antenna {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -42,7 +42,7 @@ export class Antenna {
|
||||||
})
|
})
|
||||||
public userListId: UserList['id'] | null;
|
public userListId: UserList['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserList, {
|
@ManyToOne(() => UserList, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -54,7 +54,7 @@ export class Antenna {
|
||||||
})
|
})
|
||||||
public userGroupJoiningId: UserGroupJoining['id'] | null;
|
public userGroupJoiningId: UserGroupJoining['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserGroupJoining, {
|
@ManyToOne(() => UserGroupJoining, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class App {
|
||||||
})
|
})
|
||||||
public userId: User['id'] | null;
|
public userId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,7 +11,7 @@ export class AttestationChallenge {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm';
|
import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
import { id } from '../id.js';
|
import { id } from '../id.js';
|
||||||
import { User } from './user.js';
|
import { AccessToken } from './access-token.js';
|
||||||
import { App } from './app.js';
|
import { App } from './app.js';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
|
@ -23,21 +23,27 @@ export class AuthSession {
|
||||||
...id(),
|
...id(),
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public userId: User['id'] | null;
|
public accessTokenId: AccessToken['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => AccessToken, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public accessToken: AccessToken | null;
|
||||||
|
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public appId: App['id'];
|
public appId: App['id'];
|
||||||
|
|
||||||
@ManyToOne(type => App, {
|
@ManyToOne(() => App, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public app: App | null;
|
public app: App | null;
|
||||||
|
|
||||||
|
@Column('text', {
|
||||||
|
nullable: true,
|
||||||
|
comment: 'PKCE code_challenge value, if provided (OAuth only)',
|
||||||
|
})
|
||||||
|
pkceChallenge: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class Blocking {
|
||||||
})
|
})
|
||||||
public blockeeId: User['id'];
|
public blockeeId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -34,7 +34,7 @@ export class Blocking {
|
||||||
})
|
})
|
||||||
public blockerId: User['id'];
|
public blockerId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class ChannelFollowing {
|
||||||
})
|
})
|
||||||
public followeeId: Channel['id'];
|
public followeeId: Channel['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Channel, {
|
@ManyToOne(() => Channel, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -35,7 +35,7 @@ export class ChannelFollowing {
|
||||||
})
|
})
|
||||||
public followerId: User['id'];
|
public followerId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class ChannelNotePining {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public channelId: Channel['id'];
|
public channelId: Channel['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Channel, {
|
@ManyToOne(() => Channel, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -27,7 +27,7 @@ export class ChannelNotePining {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class Channel {
|
||||||
})
|
})
|
||||||
public userId: User['id'] | null;
|
public userId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -53,7 +53,7 @@ export class Channel {
|
||||||
})
|
})
|
||||||
public bannerId: DriveFile['id'] | null;
|
public bannerId: DriveFile['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFile, {
|
@ManyToOne(() => DriveFile, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class ClipNote {
|
||||||
})
|
})
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -29,7 +29,7 @@ export class ClipNote {
|
||||||
})
|
})
|
||||||
public clipId: Clip['id'];
|
public clipId: Clip['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Clip, {
|
@ManyToOne(() => Clip, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class Clip {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -23,7 +23,7 @@ export class DriveFile {
|
||||||
})
|
})
|
||||||
public userId: User['id'] | null;
|
public userId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'RESTRICT',
|
onDelete: 'RESTRICT',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -144,7 +144,7 @@ export class DriveFile {
|
||||||
})
|
})
|
||||||
public folderId: DriveFolder['id'] | null;
|
public folderId: DriveFolder['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFolder, {
|
@ManyToOne(() => DriveFolder, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class DriveFolder {
|
||||||
})
|
})
|
||||||
public userId: User['id'] | null;
|
public userId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -41,7 +41,7 @@ export class DriveFolder {
|
||||||
})
|
})
|
||||||
public parentId: DriveFolder['id'] | null;
|
public parentId: DriveFolder['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFolder, {
|
@ManyToOne(() => DriveFolder, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class FollowRequest {
|
||||||
})
|
})
|
||||||
public followeeId: User['id'];
|
public followeeId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -33,7 +33,7 @@ export class FollowRequest {
|
||||||
})
|
})
|
||||||
public followerId: User['id'];
|
public followerId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class Following {
|
||||||
})
|
})
|
||||||
public followeeId: User['id'];
|
public followeeId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -34,7 +34,7 @@ export class Following {
|
||||||
})
|
})
|
||||||
public followerId: User['id'];
|
public followerId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class GalleryLike {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -25,7 +25,7 @@ export class GalleryLike {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public postId: GalleryPost['id'];
|
public postId: GalleryPost['id'];
|
||||||
|
|
||||||
@ManyToOne(type => GalleryPost, {
|
@ManyToOne(() => GalleryPost, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class GalleryPost {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class MessagingMessage {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -35,7 +35,7 @@ export class MessagingMessage {
|
||||||
})
|
})
|
||||||
public recipientId: User['id'] | null;
|
public recipientId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -48,7 +48,7 @@ export class MessagingMessage {
|
||||||
})
|
})
|
||||||
public groupId: UserGroup['id'] | null;
|
public groupId: UserGroup['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserGroup, {
|
@ManyToOne(() => UserGroup, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -81,7 +81,7 @@ export class MessagingMessage {
|
||||||
})
|
})
|
||||||
public fileId: DriveFile['id'] | null;
|
public fileId: DriveFile['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFile, {
|
@ManyToOne(() => DriveFile, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -134,7 +134,7 @@ export class Meta {
|
||||||
})
|
})
|
||||||
public proxyAccountId: User['id'] | null;
|
public proxyAccountId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'SET NULL',
|
onDelete: 'SET NULL',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -246,57 +246,6 @@ export class Meta {
|
||||||
})
|
})
|
||||||
public swPrivateKey: string;
|
public swPrivateKey: string;
|
||||||
|
|
||||||
@Column('boolean', {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
public enableTwitterIntegration: boolean;
|
|
||||||
|
|
||||||
@Column('varchar', {
|
|
||||||
length: 128,
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public twitterConsumerKey: string | null;
|
|
||||||
|
|
||||||
@Column('varchar', {
|
|
||||||
length: 128,
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public twitterConsumerSecret: string | null;
|
|
||||||
|
|
||||||
@Column('boolean', {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
public enableGithubIntegration: boolean;
|
|
||||||
|
|
||||||
@Column('varchar', {
|
|
||||||
length: 128,
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public githubClientId: string | null;
|
|
||||||
|
|
||||||
@Column('varchar', {
|
|
||||||
length: 128,
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public githubClientSecret: string | null;
|
|
||||||
|
|
||||||
@Column('boolean', {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
public enableDiscordIntegration: boolean;
|
|
||||||
|
|
||||||
@Column('varchar', {
|
|
||||||
length: 128,
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public discordClientId: string | null;
|
|
||||||
|
|
||||||
@Column('varchar', {
|
|
||||||
length: 128,
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public discordClientSecret: string | null;
|
|
||||||
|
|
||||||
@Column('enum', {
|
@Column('enum', {
|
||||||
enum: TranslationService,
|
enum: TranslationService,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class ModerationLog {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class MutedNote {
|
||||||
})
|
})
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -30,7 +30,7 @@ export class MutedNote {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class Muting {
|
||||||
})
|
})
|
||||||
public muteeId: User['id'];
|
public muteeId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -40,7 +40,7 @@ export class Muting {
|
||||||
})
|
})
|
||||||
public muterId: User['id'];
|
public muterId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class NoteFavorite {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -27,7 +27,7 @@ export class NoteFavorite {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class NoteReaction {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -29,7 +29,7 @@ export class NoteReaction {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class NoteThreadMuting {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -14,7 +14,7 @@ export class NoteUnread {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -24,7 +24,7 @@ export class NoteUnread {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class NoteWatching {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -35,7 +35,7 @@ export class NoteWatching {
|
||||||
})
|
})
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class Note {
|
||||||
})
|
})
|
||||||
public replyId: Note['id'] | null;
|
public replyId: Note['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -41,7 +41,7 @@ export class Note {
|
||||||
})
|
})
|
||||||
public renoteId: Note['id'] | null;
|
public renoteId: Note['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -75,7 +75,7 @@ export class Note {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -179,7 +179,7 @@ export class Note {
|
||||||
})
|
})
|
||||||
public channelId: Channel['id'] | null;
|
public channelId: Channel['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Channel, {
|
@ManyToOne(() => Channel, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public notifieeId: User['id'];
|
public notifieeId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -45,7 +45,7 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public notifierId: User['id'] | null;
|
public notifierId: User['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -89,7 +89,7 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public noteId: Note['id'] | null;
|
public noteId: Note['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -101,7 +101,7 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public followRequestId: FollowRequest['id'] | null;
|
public followRequestId: FollowRequest['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => FollowRequest, {
|
@ManyToOne(() => FollowRequest, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -113,7 +113,7 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public userGroupInvitationId: UserGroupInvitation['id'] | null;
|
public userGroupInvitationId: UserGroupInvitation['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => UserGroupInvitation, {
|
@ManyToOne(() => UserGroupInvitation, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -165,7 +165,7 @@ export class Notification {
|
||||||
})
|
})
|
||||||
public appAccessTokenId: AccessToken['id'] | null;
|
public appAccessTokenId: AccessToken['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => AccessToken, {
|
@ManyToOne(() => AccessToken, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class PageLike {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -25,7 +25,7 @@ export class PageLike {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public pageId: Page['id'];
|
public pageId: Page['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Page, {
|
@ManyToOne(() => Page, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -57,7 +57,7 @@ export class Page {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -69,7 +69,7 @@ export class Page {
|
||||||
})
|
})
|
||||||
public eyeCatchingImageId: DriveFile['id'] | null;
|
public eyeCatchingImageId: DriveFile['id'] | null;
|
||||||
|
|
||||||
@ManyToOne(type => DriveFile, {
|
@ManyToOne(() => DriveFile, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class PasswordResetRequest {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class PollVote {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -29,7 +29,7 @@ export class PollVote {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@ManyToOne(type => Note, {
|
@ManyToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -9,7 +9,7 @@ export class Poll {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public noteId: Note['id'];
|
public noteId: Note['id'];
|
||||||
|
|
||||||
@OneToOne(type => Note, {
|
@OneToOne(() => Note, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -25,7 +25,7 @@ export class RegistryItem {
|
||||||
})
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class RenoteMuting {
|
||||||
})
|
})
|
||||||
public muteeId: User['id'];
|
public muteeId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
@ -34,7 +34,7 @@ export class RenoteMuting {
|
||||||
})
|
})
|
||||||
public muterId: User['id'];
|
public muterId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class Signin {
|
||||||
@Column(id())
|
@Column(id())
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
|
|