diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md index 054418096c..8828c30764 100644 --- a/.gitlab/issue_templates/bug.md +++ b/.gitlab/issue_templates/bug.md @@ -1,7 +1,7 @@ +🔒 Found a security vulnerability? [Please disclose it responsibly.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/SECURITY.md) +🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) --> # **What happened?** @@ -30,6 +30,6 @@ # **Contribution Guidelines** -By submitting this issue, you agree to follow our [Contribution Guidelines](https://git.leafus.net/pawkey/pawkey/-/blob/stable/CONTRIBUTING.md) +By submitting this issue, you agree to follow our [Contribution Guidelines](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) - [ ] I agree to follow this project's Contribution Guidelines - [ ] I have searched the issue tracker for similar issues, and this is not a duplicate. diff --git a/.gitlab/issue_templates/feature.md b/.gitlab/issue_templates/feature.md index 478a42b41e..5976f5b1fd 100644 --- a/.gitlab/issue_templates/feature.md +++ b/.gitlab/issue_templates/feature.md @@ -1,7 +1,7 @@ +🔒 Found a security vulnerability? [Please disclose it responsibly.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/SECURITY.md) +🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) --> # **What feature would you like implemented?** @@ -16,6 +16,6 @@ # **Contribution Guidelines** -By submitting this issue, you agree to follow our [Contribution Guidelines](https://activitypub.software/TransFem-org/Pawkey/-/blob/develop/CONTRIBUTING.md) +By submitting this issue, you agree to follow our [Contribution Guidelines](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) - [ ] I agree to follow this project's Contribution Guidelines - [ ] I have searched the issue tracker for similar requests, and this is not a duplicate. diff --git a/.gitlab/merge_request_templates/default.md b/.gitlab/merge_request_templates/default.md index 9bd0a2957d..8540e2fcb9 100644 --- a/.gitlab/merge_request_templates/default.md +++ b/.gitlab/merge_request_templates/default.md @@ -6,7 +6,7 @@ %{all_commits} # **Contribution Guidelines** -By submitting this merge request, you agree to follow our [Contribution Guidelines](https://git.leafus.net/pawkey/pawkey/-/blob/stable/CONTRIBUTING.md) +By submitting this merge request, you agree to follow our [Contribution Guidelines](https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/CONTRIBUTING.md) - [ ] I agree to follow this project's Contribution Guidelines - [ ] I have made sure to test this merge request diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a9bb81f0b0..191c1fc78f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -133,7 +133,7 @@ An actual domain will be assigned so you can test the federation. - `x.y.z` is the new version you are trying to release. 3. Deploy and perform a simple QA check. Also verify that the tests passed. 4. Merge it. (Do not squash commit) -5. Create a [release](https://git.leafus.net/pawkey/pawkey/-/releases) +5. Create a [release](https://git.pawlickers.org/pawkey/pawkey/releases) - The target branch must be `stable` - The tag name must be the version diff --git a/README.md b/README.md index 3c2dff3438..117b95d157 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
- Pawkey logo + Pawkey logo **🌎 **[Pawkey](https://pawkey.dev)** is an open source, decentralized social media platform that's free forever! 🚀** diff --git a/locales/index.d.ts b/locales/index.d.ts index e6eb9fb3af..c1299676ce 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -4888,7 +4888,7 @@ export interface Locale extends ILocale { */ "repositoryUrl": string; /** - * If there is a repository where the source code is publicly available, enter its URL. If you are using Pawkey as-is (without any changes to the source code), enter https://git.leafus.net/pawkey/pawkey. + * If there is a repository where the source code is publicly available, enter its URL. If you are using Pawkey as-is (without any changes to the source code), enter https://git.pawlickers.org/pawkey/pawkey. */ "repositoryUrlDescription": string; /** diff --git a/package.json b/package.json index 276609eb58..5c4a2f2873 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "codename": "pawjob", "repository": { "type": "git", - "url": "https://git.leafus.net/pawkey/pawkey.git" + "url": "https://git.pawlickers.org/pawkey/pawkey.git" }, "packageManager": "pnpm@9.6.0", "workspaces": [ diff --git a/packages/backend/migration/1557761316509-AddSomeUrls.js b/packages/backend/migration/1557761316509-AddSomeUrls.js index f133666f1f..64e964cde7 100644 --- a/packages/backend/migration/1557761316509-AddSomeUrls.js +++ b/packages/backend/migration/1557761316509-AddSomeUrls.js @@ -6,8 +6,8 @@ export class AddSomeUrls1557761316509 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "meta" ADD "ToSUrl" character varying(512)`); - await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://git.leafus.net/pawkey/pawkey'`); - await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://git.leafus.net/pawkey/pawkey/issues/new/choose'`); + await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://git.pawlickers.org/pawkey/pawkey'`); + await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) DEFAULT 'https://git.pawlickers.org/pawkey/pawkey/issues/new'`); } async down(queryRunner) { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "feedbackUrl"`); diff --git a/packages/backend/migration/1763436210524-ChangeGITUrls.js b/packages/backend/migration/1763436210524-ChangeGITUrls.js new file mode 100644 index 0000000000..7f05d32f8a --- /dev/null +++ b/packages/backend/migration/1763436210524-ChangeGITUrls.js @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: pawinput and Pawkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class ChangeGITUrls1763436210524 { + name = 'ChangeGITUrls1763436210524' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://git.pawlickers.org/pawkey/pawkey'`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://git.pawlickers.org/pawkey/pawkey/issues/new'`); + await queryRunner.query(`UPDATE "meta" SET "repositoryUrl"=DEFAULT WHERE "repositoryUrl" IN ('https://git.leafus.net/pawkey/pawkey')`); + await queryRunner.query(`UPDATE "meta" SET "feedbackUrl"=DEFAULT WHERE "feedbackUrl" IN ('https://git.leafus.net/pawkey/pawkey/-/issues/new')`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://git.leafus.net/pawkey/pawkey'`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://git.leafus.net/pawkey/pawkey/-/issues/new'`); + await queryRunner.query(`UPDATE "meta" SET "repositoryUrl"=DEFAULT WHERE "repositoryUrl" IN ('https://git.pawlickers.org/pawkey/pawkey')`); + await queryRunner.query(`UPDATE "meta" SET "feedbackUrl"=DEFAULT WHERE "feedbackUrl" IN ('https://git.pawlickers.org/pawkey/pawkey/issues/new')`); + } +} \ No newline at end of file diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index c2e7efd456..a584016955 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -483,7 +483,7 @@ export function loadConfig(): Config { videoThumbnailGenerator: config.videoThumbnailGenerator ? config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator : null, - userAgent: `Misskey/${version} (${config.url})`, + userAgent: `Pawkey/${version} (${config.url})`, frontendEntry: frontendManifest['src/_boot_.ts'], frontendManifestExists: frontendManifestExists, frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'], diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 09fac44c8c..cb0226bd77 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -458,14 +458,14 @@ export class MiMeta { @Column('varchar', { length: 1024, - default: 'https://git.leafus.net/pawkey/pawkey/', + default: 'https://git.pawlickers.org/pawkey/pawkey/', nullable: false, }) public repositoryUrl: string | null; @Column('varchar', { length: 1024, - default: 'https://git.leafus.net/pawkey/pawkey/-/issues/new', + default: 'https://git.pawlickers.org/pawkey/pawkey/issues/new', nullable: true, }) public feedbackUrl: string | null; diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index 0910c0d36b..098c33e488 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -108,6 +108,43 @@ export class FileServerService { return; } + const body = request.method === 'GET' + ? request.query + : request.body; + + let cookieToken: string | undefined; + if (request.headers.cookie) { + const cookies = request.headers.cookie.split(';').reduce((acc, cookie) => { + const [key, value] = cookie.trim().split('='); + acc[key] = value; + return acc; + }, {} as Record); + cookieToken = cookies.token; + } + + const token = request.headers.authorization?.startsWith('Bearer ') + ? request.headers.authorization.slice(7) + : (body as any)?.['i'] ?? cookieToken; + + if (token != null && typeof token !== 'string') { + reply.code(400); + return; + } + + const [user] = await this.authenticateService.authenticate(token); + + if (!user) { + reply.code(401); + reply.send({ + error: { + message: 'Credential required.', + code: 'CREDENTIAL_REQUIRED', + id: '1384574d-a912-4b81-8601-c7b1c4085df1', + }, + }); + return; + } + const keyUrl = new URL(url); keyUrl.searchParams.forEach(k => keyUrl.searchParams.delete(k)); keyUrl.hash = ''; @@ -632,7 +669,7 @@ export class FileServerService { // https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive) const token = request.headers.authorization?.startsWith('Bearer ') ? request.headers.authorization.slice(7) - : body?.['i']; + : (body as any)?.['i']; if (token != null && typeof token !== 'string') { reply.code(400); return false; diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index eaeaecb1c2..6ca96d3093 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -95,12 +95,27 @@ export class StreamingApiServerService { ? request.headers.authorization.slice(7) : q.get('i'); + // Require authentication for WebSocket connections + if (!token) { + socket.write([ + 'HTTP/1.1 401 Unauthorized', + 'WWW-Authenticate: Bearer realm="Misskey"', + ].join('\r\n') + '\r\n\r\n'); + socket.destroy(); + return; + } + try { [user, app] = await this.authenticateService.authenticate(token); if (app !== null && !app.permission.some(p => p === 'read:account')) { throw new AuthenticationError('Your app does not have necessary permissions to use websocket API.'); } + + // Ensure we have a valid user + if (!user) { + throw new AuthenticationError('Invalid token or user not found.'); + } } catch (e) { if (e instanceof AuthenticationError) { socket.write([ diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 77554d044b..5a0605d0ae 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -19,7 +19,7 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) { externalDocs: { description: 'Repository', - url: 'https://git.leafus.net/pawkey/pawkey', + url: 'https://git.pawlickers.org/pawkey/pawkey', }, servers: [{ @@ -97,7 +97,7 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) { description: desc, externalDocs: { description: 'Source code', - url: `https://git.leafus.net/pawkey/pawkey/-/tree/stable/packages/backend/src/server/api/endpoints/${endpoint.name}.ts`, + url: `https://git.pawlickers.org/pawkey/pawkey/src/branch/stable/packages/backend/src/server/api/endpoints/${endpoint.name}.ts`, }, ...(endpoint.meta.tags ? { tags: [endpoint.meta.tags[0]], diff --git a/packages/backend/src/server/web/UrlPreviewService.ts b/packages/backend/src/server/web/UrlPreviewService.ts index 71a142fc6f..39f470dadb 100644 --- a/packages/backend/src/server/web/UrlPreviewService.ts +++ b/packages/backend/src/server/web/UrlPreviewService.ts @@ -169,8 +169,22 @@ export class UrlPreviewService { return; } - // Check rate limit + // Check authentication const auth = await this.authenticate(request); + const [user] = auth; + + if (!user) { + reply.code(401); + return reply.send({ + error: { + message: 'Credential required.', + code: 'CREDENTIAL_REQUIRED', + id: '1384574d-a912-4b81-8601-c7b1c4085df1', + }, + }); + } + + // Check rate limit if (!await this.checkRateLimit(auth, reply)) { return; } @@ -450,10 +464,21 @@ export class UrlPreviewService { private async authenticate(request: FastifyRequest<{ Querystring?: { i?: string | string[] }, Body?: { i?: string | string[] } }>): Promise { const body = request.method === 'GET' ? request.query : request.body; + // Parse token from cookie header if present + let cookieToken: string | undefined; + if (request.headers.cookie) { + const cookies = request.headers.cookie.split(';').reduce((acc, cookie) => { + const [key, value] = cookie.trim().split('='); + acc[key] = value; + return acc; + }, {} as Record); + cookieToken = cookies.token; + } + // https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive) const token = request.headers.authorization?.startsWith('Bearer ') ? request.headers.authorization.slice(7) - : body?.['i']; + : body?.['i'] ?? cookieToken; if (token != null && typeof token !== 'string') { return [undefined, undefined, getIpHash(request.ip)]; } diff --git a/packages/frontend/assets/about-icon.png b/packages/frontend/assets/about-icon.png deleted file mode 100644 index 8b73add0e9..0000000000 Binary files a/packages/frontend/assets/about-icon.png and /dev/null differ diff --git a/packages/frontend/assets/icon.png b/packages/frontend/assets/icon.png index 6ac50c8c7a..26276c9a11 100644 Binary files a/packages/frontend/assets/icon.png and b/packages/frontend/assets/icon.png differ diff --git a/packages/frontend/src/accounts.ts b/packages/frontend/src/accounts.ts index 4ee951bbd7..34491a3605 100644 --- a/packages/frontend/src/accounts.ts +++ b/packages/frontend/src/accounts.ts @@ -16,6 +16,7 @@ import { prefer } from '@/preferences.js'; import { store } from '@/store.js'; import { $i } from '@/i.js'; import { signout } from '@/signout.js'; +import Cookies from 'js-cookie'; type AccountWithToken = Misskey.entities.MeDetailed & { token: string }; @@ -186,6 +187,8 @@ export async function login(token: AccountWithToken['token'], redirect?: string) token, })); + Cookies.set('token', token, { expires: 365 * 100 }); + await addAccount(host, me, token); if (redirect) { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 2cae8a4d5d..a398b90042 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -335,7 +335,7 @@ export async function mainBoot() { } const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read'); - if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://git.leafus.net/pawkey/pawkey') { + if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://git.pawlickers.org/pawkey/pawkey') { const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, { closed: () => dispose(), }); diff --git a/packages/frontend/src/components/MkSignupDialog.rules.vue b/packages/frontend/src/components/MkSignupDialog.rules.vue index d94f6a9b73..972f7c5003 100644 --- a/packages/frontend/src/components/MkSignupDialog.rules.vue +++ b/packages/frontend/src/components/MkSignupDialog.rules.vue @@ -47,7 +47,7 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.basicNotesBeforeCreateAccount }} + {{ i18n.ts.basicNotesBeforeCreateAccount }} {{ i18n.ts.agree }} diff --git a/packages/frontend/src/components/MkUpdated.vue b/packages/frontend/src/components/MkUpdated.vue index d1f1272680..58421f8a4c 100644 --- a/packages/frontend/src/components/MkUpdated.vue +++ b/packages/frontend/src/components/MkUpdated.vue @@ -27,7 +27,7 @@ const modal = useTemplateRef('modal'); const whatIsNew = () => { modal.value?.close(); - window.open(`https://git.leafus.net/pawkey/pawkey/-/releases/${version}`, '_blank'); + window.open(`https://git.pawlickers.org/pawkey/pawkey/releases${version}`, '_blank'); }; onMounted(() => { diff --git a/packages/frontend/src/components/global/userIdWatermark.vue b/packages/frontend/src/components/global/userIdWatermark.vue index 9883048198..c0bf285c31 100644 --- a/packages/frontend/src/components/global/userIdWatermark.vue +++ b/packages/frontend/src/components/global/userIdWatermark.vue @@ -1,6 +1,6 @@