Compare commits
113 commits
376c36bde7
...
3900d2f716
Author | SHA1 | Date | |
---|---|---|---|
3900d2f716 | |||
3bf7deb233 | |||
2520633210 | |||
4574db523a | |||
263fb94f3f | |||
0e3321c106 | |||
677ee537d1 | |||
1e539e6af5 | |||
0e5f744560 | |||
8f782f8ce5 | |||
6c7f1774e3 | |||
af43df15ca | |||
5f83383ab8 | |||
8c759dde6c | |||
84d83d908a | |||
16d091497a | |||
ef53ec276a | |||
3582fd8260 | |||
6256ddbd30 | |||
00fcc238f7 | |||
9f1670d5fd | |||
ff31b8b06d | |||
e317a771b3 | |||
398ee6435b | |||
ffff2ae5ef | |||
ccc8bf0289 | |||
a231b36d59 | |||
8e9c65fab0 | |||
78a3051313 | |||
78717e85d3 | |||
a9d3cae511 | |||
bd27b7ca3a | |||
e28a9eb8e8 | |||
e5a4c5d2d0 | |||
6bba55c196 | |||
1d469f3c34 | |||
3f0228e14c | |||
73f81177b4 | |||
6a26da3516 | |||
5ea744b1b2 | |||
ae6ba05306 | |||
|
21069223e3 | ||
d4d1e03479 | |||
5513a3eb3a | |||
d5dd7c1ef5 | |||
a80521b6a8 | |||
030394b30d | |||
768d9bbdfb | |||
3ef1a4b0f9 | |||
ae59ce51b0 | |||
14a9b9bedd | |||
985a13f47f | |||
3e46433ede | |||
507b328fdf | |||
cf7449509f | |||
f46ba3f700 | |||
3cf673960b | |||
cbfd866122 | |||
b23a8dbaed | |||
80a73a7510 | |||
3dec9a47f0 | |||
b8fb7a38cc | |||
fdc682e810 | |||
fde751df8f | |||
1faf1035f9 | |||
e2ce599aca | |||
73870e85cd | |||
350f21d955 | |||
873e21f090 | |||
2afe54c121 | |||
501cf834c8 | |||
b66f7550ab | |||
18664dbca3 | |||
0f3f42eb39 | |||
71b976ec96 | |||
d3f1ad9a88 | |||
1aa3898db5 | |||
96c3744555 | |||
b023741f50 | |||
87e1e658f2 | |||
7e8d5c3b79 | |||
c785fbab6e | |||
547a1f81d4 | |||
95384d0bb2 | |||
4cc5b734e7 | |||
5d32872999 | |||
b4b1204f77 | |||
c1a51547a9 | |||
4e74d26e45 | |||
a421dd401c | |||
c4211761e6 | |||
03b673165f | |||
de18c8306d | |||
38df8dc734 | |||
11e4a8cb9b | |||
d1e0d79c19 | |||
946e862ecd | |||
97052b1f61 | |||
cda9197700 | |||
2dde8273e2 | |||
7924d5d01b | |||
de927e1f30 | |||
bdcec2b8a7 | |||
5291f29581 | |||
15b3ab6d13 | |||
79e3c20189 | |||
2f2e6a58a4 | |||
c5568cfdf3 | |||
c65fdebe26 | |||
418c88bb8f | |||
2b19b34196 | |||
7db7fdd9e2 | |||
a13e956af0 |
|
@ -133,3 +133,10 @@ redis:
|
|||
#allowedPrivateNetworks: [
|
||||
# '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
|
||||
.vscode
|
||||
.config
|
||||
.woodpecker
|
||||
Dockerfile
|
||||
build/
|
||||
built/
|
||||
|
|
|
@ -2,9 +2,10 @@ root = true
|
|||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
6
.gitattributes
vendored
|
@ -1,7 +1 @@
|
|||
*.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
|
||||
/.vscode
|
||||
!/.vscode/extensions.json
|
||||
/.vsls.json
|
||||
|
||||
# Intelij-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.
|
||||
|
||||
### Component style definitions do not have a `margin`
|
||||
Setting the `margin` of a component may be confusing.
|
||||
Instead, it should always be the user of a component that sets a `margin`.
|
||||
~~Setting the `margin` of a component may be confusing. 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
|
||||
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', () => {
|
||||
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(terser({
|
||||
toplevel: true
|
||||
|
@ -45,7 +45,7 @@ gulp.task('build:backend:script', () => {
|
|||
});
|
||||
|
||||
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({
|
||||
zindex: false
|
||||
}))
|
||||
|
|
|
@ -293,9 +293,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "الصفحات"
|
||||
integration: "التكامل"
|
||||
connectService: "اتصل"
|
||||
disconnectService: "اقطع الاتصال"
|
||||
enableLocalTimeline: "تفعيل الخيط المحلي"
|
||||
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
|
||||
disablingTimelinesInfo: "سيتمكن المديرون والمشرفون من الوصول إلى كل الخيوط الزمنية\
|
||||
|
@ -402,7 +399,6 @@ normalPassword: "الكلمة السرية جيدة"
|
|||
strongPassword: "الكلمة السرية قوية"
|
||||
passwordMatched: "التطابق صحيح!"
|
||||
passwordNotMatched: "غير متطابقتان"
|
||||
signinWith: "الولوج عبر {x}"
|
||||
signinFailed: "فشل الولوج، خطأ في اسم المستخدم أو كلمة المرور."
|
||||
tapSecurityKey: "أنقر مفتاح الأمان"
|
||||
or: "أو"
|
||||
|
|
|
@ -308,9 +308,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "পৃষ্ঠা"
|
||||
integration: "ইন্টিগ্রেশন"
|
||||
connectService: "সংযুক্ত করুন"
|
||||
disconnectService: "সংযোগ বিচ্ছিন্ন করুন"
|
||||
enableLocalTimeline: "স্থানীয় টাইমলাইন চালু করুন"
|
||||
enableGlobalTimeline: "গ্লোবাল টাইমলাইন চালু করুন"
|
||||
disablingTimelinesInfo: "আপনি এই টাইমলাইনগুলি বন্ধ করলেও প্রশাসক এবং মডারেটররা এই\
|
||||
|
@ -417,7 +414,6 @@ normalPassword: "সাধারণ পাসওয়ার্ড"
|
|||
strongPassword: "শক্তিশালী পাসওয়ার্ড"
|
||||
passwordMatched: "মিলেছে"
|
||||
passwordNotMatched: "মিলেনি"
|
||||
signinWith: "{x} এর সাহায্যে সাইন ইন করুন"
|
||||
signinFailed: "লগ ইন করা যায়নি। আপনার ব্যবহারকারীর নাম এবং পাসওয়ার্ড চেক করুন."
|
||||
tapSecurityKey: "সিকিউরিটি কী স্পর্শ করুন"
|
||||
or: "অথবা"
|
||||
|
|
|
@ -277,9 +277,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Stránky"
|
||||
integration: "Integrace"
|
||||
connectService: "Připojit"
|
||||
disconnectService: "Odpojit"
|
||||
enableLocalTimeline: "Povolit lokální čas"
|
||||
enableGlobalTimeline: "Povolit globální čas"
|
||||
enableRegistration: "Povolit registraci novým uživatelům"
|
||||
|
@ -353,7 +350,6 @@ normalPassword: "Dobré heslo"
|
|||
strongPassword: "Silné heslo"
|
||||
passwordMatched: "Hesla se schodují"
|
||||
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."
|
||||
or: "Nebo"
|
||||
language: "Jazyk"
|
||||
|
|
|
@ -321,9 +321,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Seiten"
|
||||
integration: "Integration"
|
||||
connectService: "Verbinden"
|
||||
disconnectService: "Trennen"
|
||||
enableLocalTimeline: "Lokale Chronik aktivieren"
|
||||
enableGlobalTimeline: "Globale Chronik aktivieren"
|
||||
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle\
|
||||
|
@ -433,7 +430,6 @@ normalPassword: "Durchschnittliches Passwort"
|
|||
strongPassword: "Starkes Passwort"
|
||||
passwordMatched: "Stimmt überein"
|
||||
passwordNotMatched: "Stimmt nicht überein"
|
||||
signinWith: "Mit {x} anmelden"
|
||||
signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort."
|
||||
tapSecurityKey: "Tippe deinen Sicherheitsschlüssel an"
|
||||
or: "Oder"
|
||||
|
@ -1373,18 +1369,6 @@ recommended: "Empfehlung"
|
|||
check: "Check"
|
||||
maxCustomEmojiPicker: Maximale Anzahl vorgeschlagener benutzerdefinierter 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
|
||||
signinHistoryExpires: Frühere Login-Versuche werden aus Datenschutzgründen nach 60
|
||||
Tagen automatisch gelöscht.
|
||||
|
|
|
@ -96,6 +96,8 @@ unfollow: "Unfollow"
|
|||
followRequestPending: "Follow request pending"
|
||||
renote: "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"
|
||||
pinnedNote: "Pinned note"
|
||||
you: "You"
|
||||
|
@ -187,7 +189,7 @@ clearCachedFiles: "Clear cache"
|
|||
clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote files?"
|
||||
blockedInstances: "Blocked Instances"
|
||||
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"
|
||||
mutedUsers: "Muted users"
|
||||
blockedUsers: "Blocked users"
|
||||
|
@ -311,9 +313,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pages"
|
||||
integration: "Integration"
|
||||
connectService: "Connect"
|
||||
disconnectService: "Disconnect"
|
||||
enableLocalTimeline: "Enable local timeline"
|
||||
enableGlobalTimeline: "Enable global timeline"
|
||||
disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all\
|
||||
|
@ -420,7 +419,6 @@ normalPassword: "Average password"
|
|||
strongPassword: "Strong password"
|
||||
passwordMatched: "Matches"
|
||||
passwordNotMatched: "Does not match"
|
||||
signinWith: "Sign in with {x}"
|
||||
signinFailed: "Unable to sign in. The entered username or password is incorrect."
|
||||
tapSecurityKey: "Tap your security key"
|
||||
or: "Or"
|
||||
|
@ -829,6 +827,10 @@ setTag: "Set tag"
|
|||
addTag: "Add tag"
|
||||
removeTag: "Remove tag"
|
||||
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:
|
||||
used: "This email address is already being used"
|
||||
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\
|
||||
\ your account."
|
||||
_permissions:
|
||||
"read:account": "View your account information"
|
||||
"write:account": "Edit your account information"
|
||||
"read:blocks": "View your list of blocked users"
|
||||
"write:blocks": "Edit your list of blocked users"
|
||||
"read:drive": "Access your Drive files and folders"
|
||||
"write:drive": "Edit or delete your Drive files and folders"
|
||||
"read:favorites": "View your list of favorites"
|
||||
"write:favorites": "Edit your list of favorites"
|
||||
"read:following": "View information on who you follow"
|
||||
"write:following": "Follow or unfollow other accounts"
|
||||
"read:messaging": "View your chats"
|
||||
"write:messaging": "Compose or delete chat messages"
|
||||
"read:mutes": "View your list of muted users"
|
||||
"write:mutes": "Edit your list of muted users"
|
||||
"write:notes": "Compose or delete notes"
|
||||
"read:notifications": "View your notifications"
|
||||
"write:notifications": "Manage your notifications"
|
||||
"read:reactions": "View your reactions"
|
||||
"write:reactions": "Edit your reactions"
|
||||
"write:votes": "Vote on a poll"
|
||||
"read:pages": "View your pages"
|
||||
"write:pages": "Edit or delete your pages"
|
||||
"read:page-likes": "View your likes on pages"
|
||||
"write:page-likes": "Edit your likes on pages"
|
||||
"read:user-groups": "View your user groups"
|
||||
"write:user-groups": "Edit or delete your user groups"
|
||||
"read:channels": "View your channels"
|
||||
"write:channels": "Edit your channels"
|
||||
"read:gallery": "View your gallery"
|
||||
"write:gallery": "Edit your gallery"
|
||||
"read:gallery-likes": "View your list of liked gallery posts"
|
||||
"write:gallery-likes": "Edit your list of liked gallery posts"
|
||||
"read:account": "Read account information"
|
||||
"write:account": "Edit account information"
|
||||
"read:blocks": "Read which users are blocked"
|
||||
"write:blocks": "Block and unblock users"
|
||||
"read:drive": "List files and folders in the drive"
|
||||
"write:drive": "Create, change and delete files in the drive"
|
||||
"read:favorites": "List favourited notes"
|
||||
"write:favorites": "Favorite and unfavorite notes"
|
||||
"read:following": "List followed and following users"
|
||||
"write:following": "Follow and unfollow other users"
|
||||
"read:messaging": "View chat messages and history"
|
||||
"write:messaging": "Create and delete chat messages"
|
||||
"read:mutes": "List users which are muted or whose renotes are muted"
|
||||
"write:mutes": "Mute and unmute users or their renotes"
|
||||
"write:notes": "Create and delete notes"
|
||||
"read:notifications": "Read notifications"
|
||||
"write:notifications": "Mark notifications as read and create custom notifications"
|
||||
"write:reactions": "Create and delete reactions"
|
||||
"write:votes": "Vote in polls"
|
||||
"read:pages": "List and read pages"
|
||||
"write:pages": "Create, change and delete pages"
|
||||
"read:page-likes": "List and read page likes"
|
||||
"write:page-likes": "Like and unlike pages"
|
||||
"read:user-groups": "List and view joined, owned and invited to groups"
|
||||
"write:user-groups": "Create, modify, delete, transfer, join and leave groups. Invite and ban others from groups. Accept and reject group invitations."
|
||||
"read:channels": "List and read followed and joined channels"
|
||||
"write:channels": "Create, modify, follow and unfollow channels"
|
||||
"read:gallery": "List and read gallery posts"
|
||||
"write:gallery": "Create, modify and delete gallery posts"
|
||||
"read:gallery-likes": "List and read gallery post likes"
|
||||
"write:gallery-likes": "Like and unlike gallery posts"
|
||||
_auth:
|
||||
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
||||
shareAccessAsk: "Are you sure you want to authorize this application to access your\
|
||||
|
@ -1342,16 +1343,6 @@ _deck:
|
|||
list: "List"
|
||||
mentions: "Mentions"
|
||||
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:
|
||||
_deepl:
|
||||
authKey: "DeepL Auth Key"
|
||||
|
|
|
@ -311,9 +311,6 @@ dayX: "Día {day}"
|
|||
monthX: "Mes {month}"
|
||||
yearX: "Año {year}"
|
||||
pages: "Páginas"
|
||||
integration: "Integración"
|
||||
connectService: "Conectar"
|
||||
disconnectService: "Desconectar"
|
||||
enableLocalTimeline: "Habilitar linea de tiempo local"
|
||||
enableGlobalTimeline: "Habilitar linea de tiempo global"
|
||||
disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia\
|
||||
|
@ -420,7 +417,6 @@ normalPassword: "Buena contraseña"
|
|||
strongPassword: "Muy buena contraseña"
|
||||
passwordMatched: "Correcto"
|
||||
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\
|
||||
\ y contraseña correctos."
|
||||
tapSecurityKey: "Toque la clave de seguridad"
|
||||
|
|
|
@ -311,9 +311,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pages"
|
||||
integration: "Intégrations"
|
||||
connectService: "Connexion"
|
||||
disconnectService: "Déconnexion"
|
||||
enableLocalTimeline: "Activer le fil local"
|
||||
enableGlobalTimeline: "Activer le fil global"
|
||||
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"
|
||||
passwordMatched: "Les mots de passe correspondent"
|
||||
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\
|
||||
\ et mot de passe sont corrects."
|
||||
tapSecurityKey: "Appuyez sur votre clé de sécurité"
|
||||
|
@ -1331,18 +1327,6 @@ _deck:
|
|||
list: "Listes"
|
||||
mentions: "Mentions"
|
||||
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
|
||||
stopActivityDeliveryDescription: L'activité locale ne sera pas envoyé à cette instance.
|
||||
La réception de l'activité continuera de fonctionner comme avant.
|
||||
|
|
|
@ -310,9 +310,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Halaman"
|
||||
integration: "Integrasi"
|
||||
connectService: "Sambungkan"
|
||||
disconnectService: "Putuskan"
|
||||
enableLocalTimeline: "Nyalakan linimasa lokal"
|
||||
enableGlobalTimeline: "Nyalakan linimasa global"
|
||||
disablingTimelinesInfo: "Admin dan Moderator akan selalu memiliki akses ke semua linimasa\
|
||||
|
@ -419,7 +416,6 @@ normalPassword: "Kata sandi baik"
|
|||
strongPassword: "Kata sandi kuat"
|
||||
passwordMatched: "Kata sandi sama"
|
||||
passwordNotMatched: "Kata sandi tidak sama"
|
||||
signinWith: "Masuk dengan {x}"
|
||||
signinFailed: "Tidak dapat masuk. Nama pengguna atau kata sandi yang kamu masukkan\
|
||||
\ salah."
|
||||
tapSecurityKey: "Ketuk kunci keamanan kamu"
|
||||
|
|
|
@ -304,9 +304,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pagine"
|
||||
integration: "App collegate"
|
||||
connectService: "Connessione"
|
||||
disconnectService: "Disconnessione "
|
||||
enableLocalTimeline: "Abilita Timeline locale"
|
||||
enableGlobalTimeline: "Abilita Timeline federata"
|
||||
disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e\
|
||||
|
@ -413,7 +410,6 @@ normalPassword: "Password buona"
|
|||
strongPassword: "Password forte"
|
||||
passwordMatched: "Corretta"
|
||||
passwordNotMatched: "Le password non corrispondono."
|
||||
signinWith: "Accedi con {x}"
|
||||
signinFailed: "Autenticazione non riuscita. Controlla la tua password e nome utente."
|
||||
tapSecurityKey: "Premi la chiave di sicurezza"
|
||||
or: "oppure"
|
||||
|
|
|
@ -286,9 +286,6 @@ dayX: "{day}日"
|
|||
monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "ページ"
|
||||
integration: "連携"
|
||||
connectService: "接続する"
|
||||
disconnectService: "切断する"
|
||||
enableLocalTimeline: "ローカルタイムラインを有効にする"
|
||||
enableGlobalTimeline: "グローバルタイムラインを有効にする"
|
||||
disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
|
||||
|
@ -392,7 +389,6 @@ normalPassword: "普通のパスワード"
|
|||
strongPassword: "強いパスワード"
|
||||
passwordMatched: "一致しました"
|
||||
passwordNotMatched: "一致していません"
|
||||
signinWith: "{x}でログイン"
|
||||
signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
tapSecurityKey: "セキュリティキーにタッチ"
|
||||
or: "もしくは"
|
||||
|
@ -1273,13 +1269,3 @@ _deck:
|
|||
list: "リスト"
|
||||
mentions: "あなた宛て"
|
||||
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}月"
|
||||
yearX: "{year}年"
|
||||
pages: "ページ"
|
||||
integration: "連携"
|
||||
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
|
||||
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
|
||||
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
|
||||
|
@ -391,7 +390,6 @@ normalPassword: "普通のパスワード"
|
|||
strongPassword: "ええ感じのパスワード"
|
||||
passwordMatched: "よし!一致や!"
|
||||
passwordNotMatched: "一致しとらんで?"
|
||||
signinWith: "{x}でログイン"
|
||||
or: "それか"
|
||||
language: "言語"
|
||||
uiLanguage: "UIの表示言語"
|
||||
|
|
|
@ -39,7 +39,6 @@ userList: "Tibdarin"
|
|||
securityKey: "Tasarutt n tɣellist"
|
||||
securityKeyName: "Isem n tsarutt"
|
||||
signinRequired: "Ttxil jerred"
|
||||
signinWith: "Tuqqna s {x}"
|
||||
tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
|
||||
uiLanguage: "Tutlayt n wegrudem"
|
||||
plugins: "Izegrar"
|
||||
|
|
|
@ -315,9 +315,6 @@ dayX: "{day}일"
|
|||
monthX: "{month}월"
|
||||
yearX: "{year}년"
|
||||
pages: "페이지"
|
||||
integration: "연동"
|
||||
connectService: "계정 연동"
|
||||
disconnectService: "계정 연동 해제"
|
||||
enableLocalTimeline: "로컬 타임라인 활성화"
|
||||
enableGlobalTimeline: "글로벌 타임라인 활성화"
|
||||
disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
|
||||
|
@ -438,7 +435,6 @@ normalPassword: "좋은 비밀번호"
|
|||
strongPassword: "강한 비밀번호"
|
||||
passwordMatched: "일치합니다"
|
||||
passwordNotMatched: "일치하지 않습니다"
|
||||
signinWith: "{x}로 로그인"
|
||||
signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
|
||||
tapSecurityKey: "보안 키를 터치"
|
||||
or: "혹은"
|
||||
|
|
|
@ -298,9 +298,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Strony"
|
||||
integration: "Integracja"
|
||||
connectService: "Połącz"
|
||||
disconnectService: "Rozłącz"
|
||||
enableLocalTimeline: "Włącz lokalną oś czasu"
|
||||
enableGlobalTimeline: "Włącz globalną oś czasu"
|
||||
disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do\
|
||||
|
@ -407,7 +404,6 @@ normalPassword: "Dobre hasło"
|
|||
strongPassword: "Silne hasło"
|
||||
passwordMatched: "Pasuje"
|
||||
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ą\
|
||||
\ nieprawidłowe."
|
||||
tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
|
||||
|
|
|
@ -311,9 +311,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pagini"
|
||||
integration: "Integrare"
|
||||
connectService: "Conectează"
|
||||
disconnectService: "Deconectează"
|
||||
enableLocalTimeline: "Activează cronologia locală"
|
||||
enableGlobalTimeline: "Activeaza cronologia globală"
|
||||
disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate\
|
||||
|
@ -420,7 +417,6 @@ normalPassword: "Parolă medie"
|
|||
strongPassword: "Parolă puternică"
|
||||
passwordMatched: "Se potrivește!"
|
||||
passwordNotMatched: "Nu se potrivește"
|
||||
signinWith: "Autentifică-te cu {x}"
|
||||
signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse\
|
||||
\ sunt incorecte."
|
||||
tapSecurityKey: "Apasă pe cheia ta de securitate."
|
||||
|
|
|
@ -304,9 +304,6 @@ dayX: "{day} день"
|
|||
monthX: "{month} месяц"
|
||||
yearX: "{year} год"
|
||||
pages: "Страницы"
|
||||
integration: "Интеграция"
|
||||
connectService: "Подключиться"
|
||||
disconnectService: "Отключиться"
|
||||
enableLocalTimeline: "Включить локальную ленту"
|
||||
enableGlobalTimeline: "Включить глобальную ленту"
|
||||
disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам,\
|
||||
|
@ -415,7 +412,6 @@ normalPassword: "Годный пароль"
|
|||
strongPassword: "Надёжный пароль"
|
||||
passwordMatched: "Совпали"
|
||||
passwordNotMatched: "Не совпадают"
|
||||
signinWith: "Использовать {x} для входа"
|
||||
signinFailed: "Невозможно войти в систему. Введенное вами имя пользователя или пароль\
|
||||
\ неверны."
|
||||
tapSecurityKey: "Нажмите на свой электронный ключ"
|
||||
|
|
|
@ -305,9 +305,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Stránky"
|
||||
integration: "Integrácia"
|
||||
connectService: "Pripojiť"
|
||||
disconnectService: "Odpojiť"
|
||||
enableLocalTimeline: "Povoliť lokálnu časovú os"
|
||||
enableGlobalTimeline: "Povoliť globálnu časovú os"
|
||||
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"
|
||||
passwordMatched: "Heslá 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."
|
||||
tapSecurityKey: "Ťuknite na bezpečnostný kľúč"
|
||||
or: "Alebo"
|
||||
|
|
|
@ -305,9 +305,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Сторінки"
|
||||
integration: "Інтеграція"
|
||||
connectService: "Під’єднати"
|
||||
disconnectService: "Відключитися"
|
||||
enableLocalTimeline: "Увімкнути локальну стрічку"
|
||||
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
||||
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх\
|
||||
|
@ -414,7 +411,6 @@ normalPassword: "Достатній пароль"
|
|||
strongPassword: "Міцний пароль"
|
||||
passwordMatched: "Все вірно"
|
||||
passwordNotMatched: "Паролі не співпадають"
|
||||
signinWith: "Увійти за допомогою {x}"
|
||||
signinFailed: "Не вдалося увійти. Введені ім’я користувача або пароль неправильнi."
|
||||
tapSecurityKey: "Торкніться ключа безпеки"
|
||||
or: "або"
|
||||
|
|
|
@ -305,9 +305,6 @@ dayX: "{day}"
|
|||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
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ủ"
|
||||
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\
|
||||
|
@ -415,7 +412,6 @@ normalPassword: "Mật khẩu tạm được"
|
|||
strongPassword: "Mật khẩu mạnh"
|
||||
passwordMatched: "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\
|
||||
\ bạn."
|
||||
tapSecurityKey: "Nhấn mã bảo mật của bạn"
|
||||
|
|
|
@ -284,9 +284,6 @@ dayX: "{day}日"
|
|||
monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "页面"
|
||||
integration: "关联"
|
||||
connectService: "连接"
|
||||
disconnectService: "断开连接"
|
||||
enableLocalTimeline: "启用本地时间线功能"
|
||||
enableGlobalTimeline: "启用全局时间线"
|
||||
disablingTimelinesInfo: "即使时间线功能被禁用,出于方便,管理员和数据图表也可以继续使用。"
|
||||
|
@ -390,7 +387,6 @@ normalPassword: "密码强度:中等"
|
|||
strongPassword: "密码强度:强"
|
||||
passwordMatched: "密码一致"
|
||||
passwordNotMatched: "密码不一致"
|
||||
signinWith: "以{x}登录"
|
||||
signinFailed: "无法登录,请检查您的用户名和密码是否正确。"
|
||||
tapSecurityKey: "轻触硬件安全密钥"
|
||||
or: "或者"
|
||||
|
|
|
@ -284,9 +284,6 @@ dayX: "{day}日"
|
|||
monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "頁面"
|
||||
integration: "整合"
|
||||
connectService: "己連結"
|
||||
disconnectService: "己斷開 "
|
||||
enableLocalTimeline: "開啟本地時間軸"
|
||||
enableGlobalTimeline: "啟用公開時間軸"
|
||||
disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
|
||||
|
@ -390,7 +387,6 @@ normalPassword: "密碼強度普通"
|
|||
strongPassword: "密碼強度高"
|
||||
passwordMatched: "密碼一致"
|
||||
passwordNotMatched: "密碼不一致"
|
||||
signinWith: "以{x}登錄"
|
||||
signinFailed: "登入失敗。 請檢查使用者名稱和密碼。"
|
||||
tapSecurityKey: "點擊安全密鑰"
|
||||
or: "或者"
|
||||
|
|
10
package.json
|
@ -18,7 +18,7 @@
|
|||
"migrateandstart": "yarn migrate && yarn start",
|
||||
"gulp": "gulp build",
|
||||
"watch": "yarn dev",
|
||||
"dev": "node ./scripts/dev.js",
|
||||
"dev": "node ./scripts/dev.mjs",
|
||||
"lint": "yarn workspaces foreach run lint",
|
||||
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
||||
"cy:run": "cypress run",
|
||||
|
@ -26,8 +26,8 @@
|
|||
"mocha": "yarn workspace backend run mocha",
|
||||
"test": "yarn mocha",
|
||||
"format": "gulp format",
|
||||
"clean": "node ./scripts/clean.js",
|
||||
"clean-all": "node ./scripts/clean-all.js",
|
||||
"clean": "node ./scripts/clean.mjs",
|
||||
"clean-all": "node ./scripts/clean-all.mjs",
|
||||
"cleanall": "yarn clean-all"
|
||||
},
|
||||
"resolutions": {
|
||||
|
@ -46,11 +46,11 @@
|
|||
"devDependencies": {
|
||||
"@types/gulp": "4.0.9",
|
||||
"@types/gulp-rename": "2.0.1",
|
||||
"@typescript-eslint/parser": "^5.44.0",
|
||||
"@typescript-eslint/parser": "^5.46.1",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "10.3.0",
|
||||
"start-server-and-test": "1.14.0",
|
||||
"typescript": "^4.9.3"
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"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": {
|
||||
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
|
||||
"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",
|
||||
"migrate": "npx typeorm migration:run -d ormconfig.js",
|
||||
"start": "node --experimental-json-modules ./built/index.js",
|
||||
|
@ -29,7 +29,6 @@
|
|||
"ajv": "8.11.0",
|
||||
"archiver": "5.3.1",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autwh": "0.1.0",
|
||||
"aws-sdk": "2.1165.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "1.1.5",
|
||||
|
@ -92,7 +91,6 @@
|
|||
"reflect-metadata": "0.1.13",
|
||||
"rename": "1.0.4",
|
||||
"require-all": "3.0.0",
|
||||
"rndstr": "1.0.0",
|
||||
"rss-parser": "3.12.0",
|
||||
"sanitize-html": "2.7.0",
|
||||
"semver": "7.3.7",
|
||||
|
@ -124,6 +122,7 @@
|
|||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/bull": "3.15.8",
|
||||
"@types/cbor": "6.0.0",
|
||||
"@types/color-convert": "^2.0.0",
|
||||
"@types/escape-regexp": "0.0.1",
|
||||
"@types/fluent-ffmpeg": "2.1.20",
|
||||
"@types/is-url": "1.2.30",
|
||||
|
@ -146,7 +145,6 @@
|
|||
"@types/node": "18.7.16",
|
||||
"@types/node-fetch": "3.0.3",
|
||||
"@types/nodemailer": "6.4.5",
|
||||
"@types/oauth": "^0.9.1",
|
||||
"@types/pg": "^8.6.5",
|
||||
"@types/pug": "2.0.6",
|
||||
"@types/punycode": "2.1.0",
|
||||
|
@ -161,20 +159,21 @@
|
|||
"@types/sinon": "^10.0.13",
|
||||
"@types/sinonjs__fake-timers": "8.1.2",
|
||||
"@types/speakeasy": "2.0.7",
|
||||
"@types/syslog-pro": "^1.0.0",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@types/tmp": "0.2.3",
|
||||
"@types/uuid": "8.3.4",
|
||||
"@types/web-push": "3.3.2",
|
||||
"@types/websocket": "1.0.5",
|
||||
"@types/ws": "8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
||||
"@typescript-eslint/parser": "^5.44.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
||||
"@typescript-eslint/parser": "^5.46.1",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint": "^8.29.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"execa": "6.1.0",
|
||||
"form-data": "^4.0.0",
|
||||
"sinon": "^14.0.2",
|
||||
"typescript": "^4.9.3"
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ const ev = new Xev();
|
|||
/**
|
||||
* Init process
|
||||
*/
|
||||
export default async function(): Promise<void> {
|
||||
export async function boot(): Promise<void> {
|
||||
process.title = `FoundKey (${cluster.isPrimary ? 'master' : 'worker'})`;
|
||||
|
||||
if (cluster.isPrimary || envOption.disableClustering) {
|
||||
|
|
|
@ -153,7 +153,7 @@ async function spawnWorkers(clusterLimits: Required<Config['clusterLimits']>): P
|
|||
|
||||
bootLogger.info(`Starting ${total} workers...`);
|
||||
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> {
|
||||
|
|
|
@ -38,6 +38,12 @@ export default function load(): Config {
|
|||
|
||||
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;
|
||||
|
||||
mixin.version = meta.version;
|
||||
|
|
|
@ -59,7 +59,7 @@ export type Source = {
|
|||
deliverJobMaxAttempts?: number;
|
||||
inboxJobMaxAttempts?: number;
|
||||
|
||||
syslog: {
|
||||
syslog?: {
|
||||
host: string;
|
||||
port: number;
|
||||
};
|
||||
|
@ -67,6 +67,12 @@ export type Source = {
|
|||
mediaProxy?: string;
|
||||
proxyRemoteFiles?: boolean;
|
||||
internalStoragePath?: string;
|
||||
|
||||
images?: {
|
||||
info?: string;
|
||||
notFound?: string;
|
||||
error?: string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// https://github.com/typeorm/typeorm/issues/2400
|
||||
import pg from 'pg';
|
||||
import { SECOND } from '@/const.js';
|
||||
|
||||
pg.types.setTypeParser(20, Number);
|
||||
|
||||
|
@ -8,6 +7,7 @@ import { Logger, DataSource } from 'typeorm';
|
|||
import * as highlight from 'cli-highlight';
|
||||
import config from '@/config/index.js';
|
||||
|
||||
import { SECOND } from '@/const.js';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
import { DriveFile } from '@/models/entities/drive-file.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);
|
||||
|
||||
class MyCustomLogger implements Logger {
|
||||
private highlight(sql: string) {
|
||||
private highlight(sql: string): string {
|
||||
return highlight.highlight(sql, {
|
||||
language: 'sql', ignoreIllegals: true,
|
||||
});
|
||||
}
|
||||
|
||||
public logQuery(query: string, parameters?: any[]) {
|
||||
public logQuery(query: string): void {
|
||||
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));
|
||||
}
|
||||
|
||||
public logQuerySlow(time: number, query: string, parameters?: any[]) {
|
||||
public logQuerySlow(time: number, query: string): void {
|
||||
sqlLogger.warn(this.highlight(query));
|
||||
}
|
||||
|
||||
public logSchemaBuild(message: string) {
|
||||
public logSchemaBuild(message: string): void {
|
||||
sqlLogger.info(message);
|
||||
}
|
||||
|
||||
public log(message: string) {
|
||||
public log(message: string): void {
|
||||
sqlLogger.info(message);
|
||||
}
|
||||
|
||||
public logMigration(message: string) {
|
||||
public logMigration(message: string): void {
|
||||
sqlLogger.info(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
import { EventEmitter } from 'node:events';
|
||||
import boot from '@/boot/index.js';
|
||||
import { boot } from '@/boot/index.js';
|
||||
|
||||
Error.stackTraceLimit = Infinity;
|
||||
EventEmitter.defaultMaxListeners = 128;
|
||||
|
|
|
@ -7,6 +7,16 @@ const treeAdapter = parse5.defaultTreeAdapter;
|
|||
const urlRegex = /^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 {
|
||||
const dom = parse5.parseFragment(
|
||||
// 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':
|
||||
{
|
||||
const txt = getText(node);
|
||||
const rel = node.attrs.find(x => x.name === 'rel');
|
||||
const href = node.attrs.find(x => x.name === 'href');
|
||||
const href = getAttr(node, 'href');
|
||||
|
||||
// hashtags
|
||||
if (txt.startsWith('#') && href && /\btag\b/.test(rel?.value)) {
|
||||
if (txt.startsWith('#') && href && (attrHas(node, 'rel', 'tag') || attrHas(node, 'class', 'hashtag'))) {
|
||||
text += txt;
|
||||
// mentions
|
||||
} else if (txt.startsWith('@') && !(rel && rel.value.match(/^me /))) {
|
||||
} else if (txt.startsWith('@') && !attrHas(node, 'rel', 'me')) {
|
||||
const part = txt.split('@');
|
||||
|
||||
if (part.length === 2 && href) {
|
||||
// restore the host name part
|
||||
const acct = `${txt}@${(new URL(href.value)).hostname}`;
|
||||
const acct = `${txt}@${(new URL(href)).hostname}`;
|
||||
text += acct;
|
||||
} else if (part.length === 3) {
|
||||
text += txt;
|
||||
|
@ -85,17 +94,17 @@ export function fromHtml(html: string, quoteUri?: string | null): string {
|
|||
if (!href) {
|
||||
return txt;
|
||||
}
|
||||
if (!txt || txt === href.value) { // #6383: Missing text node
|
||||
if (href.value.match(urlRegexFull)) {
|
||||
return href.value;
|
||||
if (!txt || txt === href) { // #6383: Missing text node
|
||||
if (href.match(urlRegexFull)) {
|
||||
return href;
|
||||
} else {
|
||||
return `<${href.value}>`;
|
||||
return `<${href}>`;
|
||||
}
|
||||
}
|
||||
if (href.value.match(urlRegex) && !href.value.match(urlRegexFull)) {
|
||||
return `[${txt}](<${href.value}>)`; // #6846
|
||||
if (href.match(urlRegex) && !href.match(urlRegexFull)) {
|
||||
return `[${txt}](<${href}>)`; // #6846
|
||||
} else {
|
||||
return `[${txt}](${href.value})`;
|
||||
return `[${txt}](${href})`;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -204,8 +213,7 @@ export function fromHtml(html: string, quoteUri?: string | null): string {
|
|||
|
||||
case 'span':
|
||||
{
|
||||
const nodeClass = node.attrs.find(({ name }) => name === 'class')?.value;
|
||||
if (/\bquote-inline\b/.test(nodeClass) && quoteUri && getText(node).trim() === `RE: ${quoteUri}`) {
|
||||
if (attrHas(node, 'class', 'quote-inline') && quoteUri && getText(node).trim() === `RE: ${quoteUri}`) {
|
||||
// embedded quote thingy for backwards compatibility, don't show it
|
||||
} else {
|
||||
appendChildren(node.childNodes);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export class Cache<T> {
|
||||
public cache: Map<string | null, { date: number; value: T; }>;
|
||||
public cache: Map<string, { date: number; value: T; }>;
|
||||
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']) {
|
||||
this.cache = new Map();
|
||||
|
@ -9,14 +9,14 @@ export class Cache<T> {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
public set(key: string | null, value: T): void {
|
||||
public set(key: string, value: T): void {
|
||||
this.cache.set(key, {
|
||||
date: Date.now(),
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
public get(key: string | null): T | undefined {
|
||||
public get(key: string): T | undefined {
|
||||
const cached = this.cache.get(key);
|
||||
if (cached == null) return undefined;
|
||||
|
||||
|
@ -29,7 +29,7 @@ export class Cache<T> {
|
|||
return cached.value;
|
||||
}
|
||||
|
||||
public delete(key: string | null): void {
|
||||
public delete(key: string): void {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ export class Cache<T> {
|
|||
* run to get the value. If the fetcher returns undefined, it is
|
||||
* 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);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import * as crypto from 'node:crypto';
|
||||
|
||||
const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||
const LU_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const LU_CHARS = L_CHARS + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
export function secureRndstr(length = 32, useLU = true): string {
|
||||
const chars = useLU ? LU_CHARS : L_CHARS;
|
||||
export function secureRndstrCustom(length = 32, chars: string): string {
|
||||
const chars_len = chars.length;
|
||||
|
||||
let str = '';
|
||||
|
@ -19,3 +18,8 @@ export function secureRndstr(length = 32, useLU = true): string {
|
|||
|
||||
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 { Instance } from '@/models/entities/instance.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
|
||||
// "dead" and should no longer get activities delivered to it.
|
||||
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.
|
||||
*
|
||||
|
@ -62,7 +35,7 @@ export async function skippedInstances(hosts: Array<Instance['host']>): Promise<
|
|||
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())
|
||||
public targetUserId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -27,7 +27,7 @@ export class AbuseUserReport {
|
|||
@Column(id())
|
||||
public reporterId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -39,7 +39,7 @@ export class AbuseUserReport {
|
|||
})
|
||||
public assigneeId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -41,7 +41,7 @@ export class AccessToken {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -53,7 +53,7 @@ export class AccessToken {
|
|||
})
|
||||
public appId: App['id'] | null;
|
||||
|
||||
@ManyToOne(type => App, {
|
||||
@ManyToOne(() => App, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -18,7 +18,7 @@ export class AnnouncementRead {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -28,7 +28,7 @@ export class AnnouncementRead {
|
|||
@Column(id())
|
||||
public announcementId: Announcement['id'];
|
||||
|
||||
@ManyToOne(type => Announcement, {
|
||||
@ManyToOne(() => Announcement, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -16,7 +16,7 @@ export class AntennaNote {
|
|||
})
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -29,7 +29,7 @@ export class AntennaNote {
|
|||
})
|
||||
public antennaId: Antenna['id'];
|
||||
|
||||
@ManyToOne(type => Antenna, {
|
||||
@ManyToOne(() => Antenna, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Antenna {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -42,7 +42,7 @@ export class Antenna {
|
|||
})
|
||||
public userListId: UserList['id'] | null;
|
||||
|
||||
@ManyToOne(type => UserList, {
|
||||
@ManyToOne(() => UserList, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -54,7 +54,7 @@ export class Antenna {
|
|||
})
|
||||
public userGroupJoiningId: UserGroupJoining['id'] | null;
|
||||
|
||||
@ManyToOne(type => UserGroupJoining, {
|
||||
@ManyToOne(() => UserGroupJoining, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -21,7 +21,7 @@ export class App {
|
|||
})
|
||||
public userId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'SET NULL',
|
||||
nullable: true,
|
||||
})
|
||||
|
|
|
@ -11,7 +11,7 @@ export class AttestationChallenge {
|
|||
@PrimaryColumn(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm';
|
||||
import { id } from '../id.js';
|
||||
import { User } from './user.js';
|
||||
import { AccessToken } from './access-token.js';
|
||||
import { App } from './app.js';
|
||||
|
||||
@Entity()
|
||||
|
@ -23,21 +23,27 @@ export class AuthSession {
|
|||
...id(),
|
||||
nullable: true,
|
||||
})
|
||||
public userId: User['id'] | null;
|
||||
public accessTokenId: AccessToken['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => AccessToken, {
|
||||
onDelete: 'CASCADE',
|
||||
nullable: true,
|
||||
})
|
||||
@JoinColumn()
|
||||
public user: User | null;
|
||||
public accessToken: AccessToken | null;
|
||||
|
||||
@Column(id())
|
||||
public appId: App['id'];
|
||||
|
||||
@ManyToOne(type => App, {
|
||||
@ManyToOne(() => App, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
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'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -34,7 +34,7 @@ export class Blocking {
|
|||
})
|
||||
public blockerId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -22,7 +22,7 @@ export class ChannelFollowing {
|
|||
})
|
||||
public followeeId: Channel['id'];
|
||||
|
||||
@ManyToOne(type => Channel, {
|
||||
@ManyToOne(() => Channel, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -35,7 +35,7 @@ export class ChannelFollowing {
|
|||
})
|
||||
public followerId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -18,7 +18,7 @@ export class ChannelNotePining {
|
|||
@Column(id())
|
||||
public channelId: Channel['id'];
|
||||
|
||||
@ManyToOne(type => Channel, {
|
||||
@ManyToOne(() => Channel, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -27,7 +27,7 @@ export class ChannelNotePining {
|
|||
@Column(id())
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -28,7 +28,7 @@ export class Channel {
|
|||
})
|
||||
public userId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -53,7 +53,7 @@ export class Channel {
|
|||
})
|
||||
public bannerId: DriveFile['id'] | null;
|
||||
|
||||
@ManyToOne(type => DriveFile, {
|
||||
@ManyToOne(() => DriveFile, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -16,7 +16,7 @@ export class ClipNote {
|
|||
})
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -29,7 +29,7 @@ export class ClipNote {
|
|||
})
|
||||
public clipId: Clip['id'];
|
||||
|
||||
@ManyToOne(type => Clip, {
|
||||
@ManyToOne(() => Clip, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -19,7 +19,7 @@ export class Clip {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -23,7 +23,7 @@ export class DriveFile {
|
|||
})
|
||||
public userId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'RESTRICT',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -144,7 +144,7 @@ export class DriveFile {
|
|||
})
|
||||
public folderId: DriveFolder['id'] | null;
|
||||
|
||||
@ManyToOne(type => DriveFolder, {
|
||||
@ManyToOne(() => DriveFolder, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -27,7 +27,7 @@ export class DriveFolder {
|
|||
})
|
||||
public userId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -41,7 +41,7 @@ export class DriveFolder {
|
|||
})
|
||||
public parentId: DriveFolder['id'] | null;
|
||||
|
||||
@ManyToOne(type => DriveFolder, {
|
||||
@ManyToOne(() => DriveFolder, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -20,7 +20,7 @@ export class FollowRequest {
|
|||
})
|
||||
public followeeId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -33,7 +33,7 @@ export class FollowRequest {
|
|||
})
|
||||
public followerId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Following {
|
|||
})
|
||||
public followeeId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -34,7 +34,7 @@ export class Following {
|
|||
})
|
||||
public followerId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -16,7 +16,7 @@ export class GalleryLike {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -25,7 +25,7 @@ export class GalleryLike {
|
|||
@Column(id())
|
||||
public postId: GalleryPost['id'];
|
||||
|
||||
@ManyToOne(type => GalleryPost, {
|
||||
@ManyToOne(() => GalleryPost, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -37,7 +37,7 @@ export class GalleryPost {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -22,7 +22,7 @@ export class MessagingMessage {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -35,7 +35,7 @@ export class MessagingMessage {
|
|||
})
|
||||
public recipientId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -48,7 +48,7 @@ export class MessagingMessage {
|
|||
})
|
||||
public groupId: UserGroup['id'] | null;
|
||||
|
||||
@ManyToOne(type => UserGroup, {
|
||||
@ManyToOne(() => UserGroup, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -81,7 +81,7 @@ export class MessagingMessage {
|
|||
})
|
||||
public fileId: DriveFile['id'] | null;
|
||||
|
||||
@ManyToOne(type => DriveFile, {
|
||||
@ManyToOne(() => DriveFile, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -134,7 +134,7 @@ export class Meta {
|
|||
})
|
||||
public proxyAccountId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -246,57 +246,6 @@ export class Meta {
|
|||
})
|
||||
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', {
|
||||
enum: TranslationService,
|
||||
nullable: true,
|
||||
|
|
|
@ -16,7 +16,7 @@ export class ModerationLog {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -17,7 +17,7 @@ export class MutedNote {
|
|||
})
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -30,7 +30,7 @@ export class MutedNote {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -27,7 +27,7 @@ export class Muting {
|
|||
})
|
||||
public muteeId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -40,7 +40,7 @@ export class Muting {
|
|||
})
|
||||
public muterId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -18,7 +18,7 @@ export class NoteFavorite {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -27,7 +27,7 @@ export class NoteFavorite {
|
|||
@Column(id())
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -19,7 +19,7 @@ export class NoteReaction {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -29,7 +29,7 @@ export class NoteReaction {
|
|||
@Column(id())
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -20,7 +20,7 @@ export class NoteThreadMuting {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -14,7 +14,7 @@ export class NoteUnread {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -24,7 +24,7 @@ export class NoteUnread {
|
|||
@Column(id())
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -22,7 +22,7 @@ export class NoteWatching {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -35,7 +35,7 @@ export class NoteWatching {
|
|||
})
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -27,7 +27,7 @@ export class Note {
|
|||
})
|
||||
public replyId: Note['id'] | null;
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -41,7 +41,7 @@ export class Note {
|
|||
})
|
||||
public renoteId: Note['id'] | null;
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -75,7 +75,7 @@ export class Note {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -179,7 +179,7 @@ export class Note {
|
|||
})
|
||||
public channelId: Channel['id'] | null;
|
||||
|
||||
@ManyToOne(type => Channel, {
|
||||
@ManyToOne(() => Channel, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -28,7 +28,7 @@ export class Notification {
|
|||
})
|
||||
public notifieeId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -45,7 +45,7 @@ export class Notification {
|
|||
})
|
||||
public notifierId: User['id'] | null;
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -89,7 +89,7 @@ export class Notification {
|
|||
})
|
||||
public noteId: Note['id'] | null;
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -101,7 +101,7 @@ export class Notification {
|
|||
})
|
||||
public followRequestId: FollowRequest['id'] | null;
|
||||
|
||||
@ManyToOne(type => FollowRequest, {
|
||||
@ManyToOne(() => FollowRequest, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -113,7 +113,7 @@ export class Notification {
|
|||
})
|
||||
public userGroupInvitationId: UserGroupInvitation['id'] | null;
|
||||
|
||||
@ManyToOne(type => UserGroupInvitation, {
|
||||
@ManyToOne(() => UserGroupInvitation, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -165,7 +165,7 @@ export class Notification {
|
|||
})
|
||||
public appAccessTokenId: AccessToken['id'] | null;
|
||||
|
||||
@ManyToOne(type => AccessToken, {
|
||||
@ManyToOne(() => AccessToken, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -16,7 +16,7 @@ export class PageLike {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -25,7 +25,7 @@ export class PageLike {
|
|||
@Column(id())
|
||||
public pageId: Page['id'];
|
||||
|
||||
@ManyToOne(type => Page, {
|
||||
@ManyToOne(() => Page, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -57,7 +57,7 @@ export class Page {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -69,7 +69,7 @@ export class Page {
|
|||
})
|
||||
public eyeCatchingImageId: DriveFile['id'] | null;
|
||||
|
||||
@ManyToOne(type => DriveFile, {
|
||||
@ManyToOne(() => DriveFile, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -22,7 +22,7 @@ export class PasswordResetRequest {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -19,7 +19,7 @@ export class PollVote {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -29,7 +29,7 @@ export class PollVote {
|
|||
@Column(id())
|
||||
public noteId: Note['id'];
|
||||
|
||||
@ManyToOne(type => Note, {
|
||||
@ManyToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -9,7 +9,7 @@ export class Poll {
|
|||
@PrimaryColumn(id())
|
||||
public noteId: Note['id'];
|
||||
|
||||
@OneToOne(type => Note, {
|
||||
@OneToOne(() => Note, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -25,7 +25,7 @@ export class RegistryItem {
|
|||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -21,7 +21,7 @@ export class RenoteMuting {
|
|||
})
|
||||
public muteeId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
@ -34,7 +34,7 @@ export class RenoteMuting {
|
|||
})
|
||||
public muterId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|
|
@ -16,7 +16,7 @@ export class Signin {
|
|||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
|
|