mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-01-21 06:18:19 +00:00
Merge branch 'main' into reorganize-api-endpoints
This commit is contained in:
commit
425709251d
68 changed files with 1037 additions and 535 deletions
|
@ -280,13 +280,15 @@ steps:
|
||||||
# using https://github.com/pksunkara/cargo-workspaces
|
# using https://github.com/pksunkara/cargo-workspaces
|
||||||
publish_to_crates_io:
|
publish_to_crates_io:
|
||||||
image: *rust_image
|
image: *rust_image
|
||||||
|
environment:
|
||||||
|
CARGO_API_TOKEN:
|
||||||
|
from_secret: cargo_api_token
|
||||||
commands:
|
commands:
|
||||||
- *install_binstall
|
- *install_binstall
|
||||||
# Install cargo-workspaces
|
# Install cargo-workspaces
|
||||||
- cargo binstall -y cargo-workspaces
|
- cargo binstall -y cargo-workspaces
|
||||||
- cp -r migrations crates/db_schema/
|
- cp -r migrations crates/db_schema/
|
||||||
- cargo workspaces publish --token "$CARGO_API_TOKEN" --from-git --allow-dirty --no-verify --allow-branch "${CI_COMMIT_TAG}" --yes custom "${CI_COMMIT_TAG}"
|
- cargo workspaces publish --token "$CARGO_API_TOKEN" --from-git --allow-dirty --no-verify --allow-branch "${CI_COMMIT_TAG}" --yes custom "${CI_COMMIT_TAG}"
|
||||||
secrets: [cargo_api_token]
|
|
||||||
when:
|
when:
|
||||||
- event: tag
|
- event: tag
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
"lemmy-js-client": "0.20.0-api-v4.7",
|
"lemmy-js-client": "0.20.0-api-v4.8",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"ts-jest": "^29.1.0",
|
"ts-jest": "^29.1.0",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
|
|
|
@ -30,8 +30,8 @@ importers:
|
||||||
specifier: ^29.5.0
|
specifier: ^29.5.0
|
||||||
version: 29.7.0(@types/node@22.9.0)
|
version: 29.7.0(@types/node@22.9.0)
|
||||||
lemmy-js-client:
|
lemmy-js-client:
|
||||||
specifier: 0.20.0-api-v4.7
|
specifier: 0.20.0-api-v4.8
|
||||||
version: 0.20.0-api-v4.7
|
version: 0.20.0-api-v4.8
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.2.5
|
specifier: ^3.2.5
|
||||||
version: 3.3.3
|
version: 3.3.3
|
||||||
|
@ -1167,8 +1167,8 @@ packages:
|
||||||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
lemmy-js-client@0.20.0-api-v4.7:
|
lemmy-js-client@0.20.0-api-v4.8:
|
||||||
resolution: {integrity: sha512-wfvzJl1kJw1tmpYpFU+yYDfwFr3lO21QFLtXjH0EeUdeJkkzvnJlu2xt27De42+04N5jKmMTNTI/RcIR9KfCqA==}
|
resolution: {integrity: sha512-h+qgWXP4kUrr2va//WTGT6EXDUHAf3hJpitpD9SX9avlBRyVpp31pJ5BPm1G4kR7KPPyKO/nmAS+7HGKtGkRKA==}
|
||||||
|
|
||||||
leven@3.1.0:
|
leven@3.1.0:
|
||||||
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
||||||
|
@ -3077,7 +3077,7 @@ snapshots:
|
||||||
|
|
||||||
kleur@3.0.3: {}
|
kleur@3.0.3: {}
|
||||||
|
|
||||||
lemmy-js-client@0.20.0-api-v4.7: {}
|
lemmy-js-client@0.20.0-api-v4.8: {}
|
||||||
|
|
||||||
leven@3.1.0: {}
|
leven@3.1.0: {}
|
||||||
|
|
||||||
|
|
|
@ -25,17 +25,17 @@ import {
|
||||||
getComments,
|
getComments,
|
||||||
createComment,
|
createComment,
|
||||||
getCommunityByName,
|
getCommunityByName,
|
||||||
blockInstance,
|
|
||||||
waitUntil,
|
waitUntil,
|
||||||
alphaUrl,
|
alphaUrl,
|
||||||
delta,
|
delta,
|
||||||
betaAllowedInstances,
|
|
||||||
searchPostLocal,
|
searchPostLocal,
|
||||||
longDelay,
|
longDelay,
|
||||||
editCommunity,
|
editCommunity,
|
||||||
unfollows,
|
unfollows,
|
||||||
getMyUser,
|
getMyUser,
|
||||||
|
userBlockInstance,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
|
import { AdminAllowInstanceParams } from "lemmy-js-client/dist/types/AdminAllowInstanceParams";
|
||||||
import { EditCommunity, EditSite } from "lemmy-js-client";
|
import { EditCommunity, EditSite } from "lemmy-js-client";
|
||||||
|
|
||||||
beforeAll(setupLogins);
|
beforeAll(setupLogins);
|
||||||
|
@ -364,7 +364,7 @@ test("User blocks instance, communities are hidden", async () => {
|
||||||
expect(listing_ids).toContain(postRes.post_view.post.ap_id);
|
expect(listing_ids).toContain(postRes.post_view.post.ap_id);
|
||||||
|
|
||||||
// block the beta instance
|
// block the beta instance
|
||||||
await blockInstance(alpha, alphaPost.community.instance_id, true);
|
await userBlockInstance(alpha, alphaPost.community.instance_id, true);
|
||||||
|
|
||||||
// after blocking, post should not be in listing
|
// after blocking, post should not be in listing
|
||||||
let listing2 = await getPosts(alpha, "All");
|
let listing2 = await getPosts(alpha, "All");
|
||||||
|
@ -372,7 +372,7 @@ test("User blocks instance, communities are hidden", async () => {
|
||||||
expect(listing_ids2.indexOf(postRes.post_view.post.ap_id)).toBe(-1);
|
expect(listing_ids2.indexOf(postRes.post_view.post.ap_id)).toBe(-1);
|
||||||
|
|
||||||
// unblock instance again
|
// unblock instance again
|
||||||
await blockInstance(alpha, alphaPost.community.instance_id, false);
|
await userBlockInstance(alpha, alphaPost.community.instance_id, false);
|
||||||
|
|
||||||
// post should be included in listing
|
// post should be included in listing
|
||||||
let listing3 = await getPosts(alpha, "All");
|
let listing3 = await getPosts(alpha, "All");
|
||||||
|
@ -456,9 +456,12 @@ test("Dont receive community activities after unsubscribe", async () => {
|
||||||
expect(communityRes1.community_view.counts.subscribers).toBe(2);
|
expect(communityRes1.community_view.counts.subscribers).toBe(2);
|
||||||
|
|
||||||
// temporarily block alpha, so that it doesn't know about unfollow
|
// temporarily block alpha, so that it doesn't know about unfollow
|
||||||
let editSiteForm: EditSite = {};
|
var allow_instance_params: AdminAllowInstanceParams = {
|
||||||
editSiteForm.allowed_instances = ["lemmy-epsilon"];
|
instance: "lemmy-alpha",
|
||||||
await beta.editSite(editSiteForm);
|
allow: false,
|
||||||
|
reason: undefined,
|
||||||
|
};
|
||||||
|
await beta.adminAllowInstance(allow_instance_params);
|
||||||
await longDelay();
|
await longDelay();
|
||||||
|
|
||||||
// unfollow
|
// unfollow
|
||||||
|
@ -472,8 +475,8 @@ test("Dont receive community activities after unsubscribe", async () => {
|
||||||
expect(communityRes2.community_view.counts.subscribers).toBe(2);
|
expect(communityRes2.community_view.counts.subscribers).toBe(2);
|
||||||
|
|
||||||
// unblock alpha
|
// unblock alpha
|
||||||
editSiteForm.allowed_instances = betaAllowedInstances;
|
allow_instance_params.allow = true;
|
||||||
await beta.editSite(editSiteForm);
|
await beta.adminAllowInstance(allow_instance_params);
|
||||||
await longDelay();
|
await longDelay();
|
||||||
|
|
||||||
// create a post, it shouldnt reach beta
|
// create a post, it shouldnt reach beta
|
||||||
|
|
|
@ -41,6 +41,7 @@ import {
|
||||||
getMyUser,
|
getMyUser,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
import { PostView } from "lemmy-js-client/dist/types/PostView";
|
import { PostView } from "lemmy-js-client/dist/types/PostView";
|
||||||
|
import { AdminBlockInstanceParams } from "lemmy-js-client/dist/types/AdminBlockInstanceParams";
|
||||||
import { EditSite, ResolveObject } from "lemmy-js-client";
|
import { EditSite, ResolveObject } from "lemmy-js-client";
|
||||||
|
|
||||||
let betaCommunity: CommunityView | undefined;
|
let betaCommunity: CommunityView | undefined;
|
||||||
|
@ -88,12 +89,12 @@ async function assertPostFederation(
|
||||||
}
|
}
|
||||||
|
|
||||||
test("Create a post", async () => {
|
test("Create a post", async () => {
|
||||||
// Setup some allowlists and blocklists
|
// Block alpha
|
||||||
const editSiteForm: EditSite = {};
|
var block_instance_params: AdminBlockInstanceParams = {
|
||||||
|
instance: "lemmy-alpha",
|
||||||
editSiteForm.allowed_instances = [];
|
block: true,
|
||||||
editSiteForm.blocked_instances = ["lemmy-alpha"];
|
};
|
||||||
await epsilon.editSite(editSiteForm);
|
await epsilon.adminBlockInstance(block_instance_params);
|
||||||
|
|
||||||
if (!betaCommunity) {
|
if (!betaCommunity) {
|
||||||
throw "Missing beta community";
|
throw "Missing beta community";
|
||||||
|
@ -133,11 +134,9 @@ test("Create a post", async () => {
|
||||||
resolvePost(epsilon, postRes.post_view.post),
|
resolvePost(epsilon, postRes.post_view.post),
|
||||||
).rejects.toStrictEqual(Error("not_found"));
|
).rejects.toStrictEqual(Error("not_found"));
|
||||||
|
|
||||||
// remove added allow/blocklists
|
// remove blocked instance
|
||||||
editSiteForm.allowed_instances = [];
|
block_instance_params.block = false;
|
||||||
editSiteForm.blocked_instances = [];
|
await epsilon.adminBlockInstance(block_instance_params);
|
||||||
await delta.editSite(editSiteForm);
|
|
||||||
await epsilon.editSite(editSiteForm);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Create a post in a non-existent community", async () => {
|
test("Create a post in a non-existent community", async () => {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import {
|
import {
|
||||||
|
AdminBlockInstanceParams,
|
||||||
ApproveCommunityPendingFollower,
|
ApproveCommunityPendingFollower,
|
||||||
BlockCommunity,
|
BlockCommunity,
|
||||||
BlockCommunityResponse,
|
BlockCommunityResponse,
|
||||||
BlockInstance,
|
|
||||||
BlockInstanceResponse,
|
|
||||||
CommunityId,
|
CommunityId,
|
||||||
CommunityVisibility,
|
CommunityVisibility,
|
||||||
CreatePrivateMessageReport,
|
CreatePrivateMessageReport,
|
||||||
|
@ -22,11 +21,13 @@ import {
|
||||||
PostView,
|
PostView,
|
||||||
PrivateMessageReportResponse,
|
PrivateMessageReportResponse,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
|
UserBlockInstanceParams,
|
||||||
} from "lemmy-js-client";
|
} from "lemmy-js-client";
|
||||||
import { CreatePost } from "lemmy-js-client/dist/types/CreatePost";
|
import { CreatePost } from "lemmy-js-client/dist/types/CreatePost";
|
||||||
import { DeletePost } from "lemmy-js-client/dist/types/DeletePost";
|
import { DeletePost } from "lemmy-js-client/dist/types/DeletePost";
|
||||||
import { EditPost } from "lemmy-js-client/dist/types/EditPost";
|
import { EditPost } from "lemmy-js-client/dist/types/EditPost";
|
||||||
import { EditSite } from "lemmy-js-client/dist/types/EditSite";
|
import { EditSite } from "lemmy-js-client/dist/types/EditSite";
|
||||||
|
import { AdminAllowInstanceParams } from "lemmy-js-client/dist/types/AdminAllowInstanceParams";
|
||||||
import { FeaturePost } from "lemmy-js-client/dist/types/FeaturePost";
|
import { FeaturePost } from "lemmy-js-client/dist/types/FeaturePost";
|
||||||
import { GetComments } from "lemmy-js-client/dist/types/GetComments";
|
import { GetComments } from "lemmy-js-client/dist/types/GetComments";
|
||||||
import { GetCommentsResponse } from "lemmy-js-client/dist/types/GetCommentsResponse";
|
import { GetCommentsResponse } from "lemmy-js-client/dist/types/GetCommentsResponse";
|
||||||
|
@ -105,13 +106,6 @@ export const gamma = new LemmyHttp(gammaUrl, { fetchFunction });
|
||||||
export const delta = new LemmyHttp(deltaUrl, { fetchFunction });
|
export const delta = new LemmyHttp(deltaUrl, { fetchFunction });
|
||||||
export const epsilon = new LemmyHttp(epsilonUrl, { fetchFunction });
|
export const epsilon = new LemmyHttp(epsilonUrl, { fetchFunction });
|
||||||
|
|
||||||
export const betaAllowedInstances = [
|
|
||||||
"lemmy-alpha",
|
|
||||||
"lemmy-gamma",
|
|
||||||
"lemmy-delta",
|
|
||||||
"lemmy-epsilon",
|
|
||||||
];
|
|
||||||
|
|
||||||
const password = "lemmylemmy";
|
const password = "lemmylemmy";
|
||||||
|
|
||||||
export async function setupLogins() {
|
export async function setupLogins() {
|
||||||
|
@ -169,30 +163,29 @@ export async function setupLogins() {
|
||||||
rate_limit_comment: 999,
|
rate_limit_comment: 999,
|
||||||
rate_limit_search: 999,
|
rate_limit_search: 999,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the blocks and auths for each
|
|
||||||
editSiteForm.allowed_instances = [
|
|
||||||
"lemmy-beta",
|
|
||||||
"lemmy-gamma",
|
|
||||||
"lemmy-delta",
|
|
||||||
"lemmy-epsilon",
|
|
||||||
];
|
|
||||||
await alpha.editSite(editSiteForm);
|
await alpha.editSite(editSiteForm);
|
||||||
|
|
||||||
editSiteForm.allowed_instances = betaAllowedInstances;
|
|
||||||
await beta.editSite(editSiteForm);
|
await beta.editSite(editSiteForm);
|
||||||
|
|
||||||
editSiteForm.allowed_instances = [
|
|
||||||
"lemmy-alpha",
|
|
||||||
"lemmy-beta",
|
|
||||||
"lemmy-delta",
|
|
||||||
"lemmy-epsilon",
|
|
||||||
];
|
|
||||||
await gamma.editSite(editSiteForm);
|
await gamma.editSite(editSiteForm);
|
||||||
|
|
||||||
// Setup delta allowed instance
|
|
||||||
editSiteForm.allowed_instances = ["lemmy-beta"];
|
|
||||||
await delta.editSite(editSiteForm);
|
await delta.editSite(editSiteForm);
|
||||||
|
await epsilon.editSite(editSiteForm);
|
||||||
|
|
||||||
|
// Set the blocks for each
|
||||||
|
await allowInstance(alpha, "lemmy-beta");
|
||||||
|
await allowInstance(alpha, "lemmy-gamma");
|
||||||
|
await allowInstance(alpha, "lemmy-delta");
|
||||||
|
await allowInstance(alpha, "lemmy-epsilon");
|
||||||
|
|
||||||
|
await allowInstance(beta, "lemmy-alpha");
|
||||||
|
await allowInstance(beta, "lemmy-gamma");
|
||||||
|
await allowInstance(beta, "lemmy-delta");
|
||||||
|
await allowInstance(beta, "lemmy-epsilon");
|
||||||
|
|
||||||
|
await allowInstance(gamma, "lemmy-alpha");
|
||||||
|
await allowInstance(gamma, "lemmy-beta");
|
||||||
|
await allowInstance(gamma, "lemmy-delta");
|
||||||
|
await allowInstance(gamma, "lemmy-epsilon");
|
||||||
|
|
||||||
|
await allowInstance(delta, "lemmy-beta");
|
||||||
|
|
||||||
// Create the main alpha/beta communities
|
// Create the main alpha/beta communities
|
||||||
// Ignore thrown errors of duplicates
|
// Ignore thrown errors of duplicates
|
||||||
|
@ -209,6 +202,17 @@ export async function setupLogins() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function allowInstance(api: LemmyHttp, instance: string) {
|
||||||
|
const params: AdminAllowInstanceParams = {
|
||||||
|
instance,
|
||||||
|
allow: true,
|
||||||
|
};
|
||||||
|
// Ignore errors from duplicate allows (because setup gets called for each test file)
|
||||||
|
try {
|
||||||
|
await api.adminAllowInstance(params);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
export async function createPost(
|
export async function createPost(
|
||||||
api: LemmyHttp,
|
api: LemmyHttp,
|
||||||
community_id: number,
|
community_id: number,
|
||||||
|
@ -856,16 +860,16 @@ export function getPosts(
|
||||||
return api.getPosts(form);
|
return api.getPosts(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function blockInstance(
|
export function userBlockInstance(
|
||||||
api: LemmyHttp,
|
api: LemmyHttp,
|
||||||
instance_id: InstanceId,
|
instance_id: InstanceId,
|
||||||
block: boolean,
|
block: boolean,
|
||||||
): Promise<BlockInstanceResponse> {
|
): Promise<SuccessResponse> {
|
||||||
let form: BlockInstance = {
|
let form: UserBlockInstanceParams = {
|
||||||
instance_id,
|
instance_id,
|
||||||
block,
|
block,
|
||||||
};
|
};
|
||||||
return api.blockInstance(form);
|
return api.userBlockInstance(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function blockCommunity(
|
export function blockCommunity(
|
||||||
|
|
|
@ -24,7 +24,12 @@ import {
|
||||||
saveUserSettingsBio,
|
saveUserSettingsBio,
|
||||||
getMyUser,
|
getMyUser,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
import { LemmyHttp, SaveUserSettings, UploadImage } from "lemmy-js-client";
|
import {
|
||||||
|
EditSite,
|
||||||
|
LemmyHttp,
|
||||||
|
SaveUserSettings,
|
||||||
|
UploadImage,
|
||||||
|
} from "lemmy-js-client";
|
||||||
import { GetPosts } from "lemmy-js-client/dist/types/GetPosts";
|
import { GetPosts } from "lemmy-js-client/dist/types/GetPosts";
|
||||||
|
|
||||||
beforeAll(setupLogins);
|
beforeAll(setupLogins);
|
||||||
|
@ -146,9 +151,14 @@ test("Create user with Arabic name", async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Create user with accept-language", async () => {
|
test("Create user with accept-language", async () => {
|
||||||
|
const edit: EditSite = {
|
||||||
|
discussion_languages: [32],
|
||||||
|
};
|
||||||
|
await alpha.editSite(edit);
|
||||||
|
|
||||||
let lemmy_http = new LemmyHttp(alphaUrl, {
|
let lemmy_http = new LemmyHttp(alphaUrl, {
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language#syntax
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language#syntax
|
||||||
headers: { "Accept-Language": "fr-CH, en;q=0.8, de;q=0.7, *;q=0.5" },
|
headers: { "Accept-Language": "fr-CH, en;q=0.8, *;q=0.5" },
|
||||||
});
|
});
|
||||||
let user = await registerUser(lemmy_http, alphaUrl);
|
let user = await registerUser(lemmy_http, alphaUrl);
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,15 @@
|
||||||
#
|
#
|
||||||
# Requires pict-rs 0.5
|
# Requires pict-rs 0.5
|
||||||
"ProxyAllImages"
|
"ProxyAllImages"
|
||||||
|
# Allows bypassing proxy for specific image hosts when using ProxyAllImages.
|
||||||
|
#
|
||||||
|
# imgur.com is bypassed by default to avoid rate limit errors. When specifying any bypass
|
||||||
|
# in the config, this default is ignored and you need to list imgur explicitly. To proxy imgur
|
||||||
|
# requests, specify a noop bypass list, eg `proxy_bypass_domains ["example.org"]`.
|
||||||
|
proxy_bypass_domains: [
|
||||||
|
"i.imgur.com"
|
||||||
|
/* ... */
|
||||||
|
]
|
||||||
# Timeout for uploading images to pictrs (in seconds)
|
# Timeout for uploading images to pictrs (in seconds)
|
||||||
upload_timeout: 30
|
upload_timeout: 30
|
||||||
# Resize post thumbnails to this maximum width/height.
|
# Resize post thumbnails to this maximum width/height.
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{ModAddCommunity, ModAddCommunityForm},
|
mod_log::moderator::{ModAddCommunity, ModAddCommunityForm},
|
||||||
},
|
},
|
||||||
traits::{Crud, Joinable},
|
traits::{Crud, Joinable},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ use lemmy_db_schema::{
|
||||||
CommunityPersonBanForm,
|
CommunityPersonBanForm,
|
||||||
},
|
},
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
mod_log::moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
||||||
},
|
},
|
||||||
traits::{Bannable, Crud, Followable},
|
traits::{Bannable, Crud, Followable},
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::{Community, CommunityUpdateForm},
|
community::{Community, CommunityUpdateForm},
|
||||||
moderator::{ModHideCommunity, ModHideCommunityForm},
|
mod_log::moderator::{ModHideCommunity, ModHideCommunityForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||||
moderator::{ModTransferCommunity, ModTransferCommunityForm},
|
mod_log::moderator::{ModTransferCommunity, ModTransferCommunityForm},
|
||||||
},
|
},
|
||||||
traits::{Crud, Joinable},
|
traits::{Crud, Joinable},
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@ use lemmy_db_schema::{
|
||||||
CommunityPersonBanForm,
|
CommunityPersonBanForm,
|
||||||
},
|
},
|
||||||
local_site::LocalSite,
|
local_site::LocalSite,
|
||||||
moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
mod_log::moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
||||||
person::Person,
|
person::Person,
|
||||||
},
|
},
|
||||||
traits::{Bannable, Crud, Followable},
|
traits::{Bannable, Crud, Followable},
|
||||||
|
|
|
@ -7,7 +7,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
local_user::{LocalUser, LocalUserUpdateForm},
|
local_user::{LocalUser, LocalUserUpdateForm},
|
||||||
moderator::{ModAdd, ModAddForm},
|
mod_log::moderator::{ModAdd, ModAddForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
login_token::LoginToken,
|
login_token::LoginToken,
|
||||||
moderator::{ModBan, ModBanForm},
|
mod_log::moderator::{ModBan, ModBanForm},
|
||||||
person::{Person, PersonUpdateForm},
|
person::{Person, PersonUpdateForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::Community,
|
community::Community,
|
||||||
moderator::{ModFeaturePost, ModFeaturePostForm},
|
mod_log::moderator::{ModFeaturePost, ModFeaturePostForm},
|
||||||
post::{Post, PostUpdateForm},
|
post::{Post, PostUpdateForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use lemmy_api_common::{
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
moderator::{ModLockPost, ModLockPostForm},
|
mod_log::moderator::{ModLockPost, ModLockPostForm},
|
||||||
post::{Post, PostUpdateForm},
|
post::{Post, PostUpdateForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
|
|
53
crates/api/src/site/admin_allow_instance.rs
Normal file
53
crates/api/src/site/admin_allow_instance.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
site::AdminAllowInstanceParams,
|
||||||
|
utils::is_admin,
|
||||||
|
LemmyErrorType,
|
||||||
|
SuccessResponse,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::{
|
||||||
|
federation_allowlist::{FederationAllowList, FederationAllowListForm},
|
||||||
|
instance::Instance,
|
||||||
|
mod_log::admin::{AdminAllowInstance, AdminAllowInstanceForm},
|
||||||
|
};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn admin_allow_instance(
|
||||||
|
data: Json<AdminAllowInstanceParams>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
) -> LemmyResult<Json<SuccessResponse>> {
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let blocklist = Instance::blocklist(&mut context.pool()).await?;
|
||||||
|
if !blocklist.is_empty() {
|
||||||
|
Err(LemmyErrorType::CannotCombineFederationBlocklistAndAllowlist)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let instance_id = Instance::read_or_create(&mut context.pool(), data.instance.clone())
|
||||||
|
.await?
|
||||||
|
.id;
|
||||||
|
let form = FederationAllowListForm {
|
||||||
|
instance_id,
|
||||||
|
updated: None,
|
||||||
|
};
|
||||||
|
if data.allow {
|
||||||
|
FederationAllowList::allow(&mut context.pool(), &form).await?;
|
||||||
|
} else {
|
||||||
|
FederationAllowList::unallow(&mut context.pool(), instance_id).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mod_log_form = AdminAllowInstanceForm {
|
||||||
|
instance_id,
|
||||||
|
admin_person_id: local_user_view.person.id,
|
||||||
|
reason: data.reason.clone(),
|
||||||
|
allowed: data.allow,
|
||||||
|
};
|
||||||
|
AdminAllowInstance::insert(&mut context.pool(), &mod_log_form).await?;
|
||||||
|
|
||||||
|
Ok(Json(SuccessResponse::default()))
|
||||||
|
}
|
56
crates/api/src/site/admin_block_instance.rs
Normal file
56
crates/api/src/site/admin_block_instance.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
site::AdminBlockInstanceParams,
|
||||||
|
utils::is_admin,
|
||||||
|
LemmyErrorType,
|
||||||
|
SuccessResponse,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::{
|
||||||
|
federation_blocklist::{FederationBlockList, FederationBlockListForm},
|
||||||
|
instance::Instance,
|
||||||
|
mod_log::admin::{AdminBlockInstance, AdminBlockInstanceForm},
|
||||||
|
};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn admin_block_instance(
|
||||||
|
data: Json<AdminBlockInstanceParams>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
) -> LemmyResult<Json<SuccessResponse>> {
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let allowlist = Instance::allowlist(&mut context.pool()).await?;
|
||||||
|
if !allowlist.is_empty() {
|
||||||
|
Err(LemmyErrorType::CannotCombineFederationBlocklistAndAllowlist)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let instance_id = Instance::read_or_create(&mut context.pool(), data.instance.clone())
|
||||||
|
.await?
|
||||||
|
.id;
|
||||||
|
let form = FederationBlockListForm {
|
||||||
|
instance_id,
|
||||||
|
expires: data.expires,
|
||||||
|
updated: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if data.block {
|
||||||
|
FederationBlockList::block(&mut context.pool(), &form).await?;
|
||||||
|
} else {
|
||||||
|
FederationBlockList::unblock(&mut context.pool(), instance_id).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mod_log_form = AdminBlockInstanceForm {
|
||||||
|
instance_id,
|
||||||
|
admin_person_id: local_user_view.person.id,
|
||||||
|
blocked: data.block,
|
||||||
|
reason: data.reason.clone(),
|
||||||
|
when_: data.expires,
|
||||||
|
};
|
||||||
|
AdminBlockInstance::insert(&mut context.pool(), &mod_log_form).await?;
|
||||||
|
|
||||||
|
Ok(Json(SuccessResponse::default()))
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ use lemmy_db_schema::{
|
||||||
language::Language,
|
language::Language,
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
local_user::{LocalUser, LocalUserUpdateForm},
|
local_user::{LocalUser, LocalUserUpdateForm},
|
||||||
moderator::{ModAdd, ModAddForm},
|
mod_log::moderator::{ModAdd, ModAddForm},
|
||||||
oauth_provider::OAuthProvider,
|
oauth_provider::OAuthProvider,
|
||||||
tagline::Tagline,
|
tagline::Tagline,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
pub mod block;
|
pub mod admin_allow_instance;
|
||||||
|
pub mod admin_block_instance;
|
||||||
pub mod federated_instances;
|
pub mod federated_instances;
|
||||||
pub mod leave_admin;
|
pub mod leave_admin;
|
||||||
pub mod list_all_media;
|
pub mod list_all_media;
|
||||||
pub mod mod_log;
|
pub mod mod_log;
|
||||||
pub mod purge;
|
pub mod purge;
|
||||||
pub mod registration_applications;
|
pub mod registration_applications;
|
||||||
|
pub mod user_block_instance;
|
||||||
|
|
|
@ -7,6 +7,8 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{source::local_site::LocalSite, ModlogActionType};
|
use lemmy_db_schema::{source::local_site::LocalSite, ModlogActionType};
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_db_views_moderator::structs::{
|
use lemmy_db_views_moderator::structs::{
|
||||||
|
AdminAllowInstanceView,
|
||||||
|
AdminBlockInstanceView,
|
||||||
AdminPurgeCommentView,
|
AdminPurgeCommentView,
|
||||||
AdminPurgeCommunityView,
|
AdminPurgeCommunityView,
|
||||||
AdminPurgePersonView,
|
AdminPurgePersonView,
|
||||||
|
@ -121,6 +123,8 @@ pub async fn get_mod_log(
|
||||||
admin_purged_communities,
|
admin_purged_communities,
|
||||||
admin_purged_posts,
|
admin_purged_posts,
|
||||||
admin_purged_comments,
|
admin_purged_comments,
|
||||||
|
admin_block_instance,
|
||||||
|
admin_allow_instance,
|
||||||
) = if data.community_id.is_none() {
|
) = if data.community_id.is_none() {
|
||||||
(
|
(
|
||||||
match type_ {
|
match type_ {
|
||||||
|
@ -161,6 +165,18 @@ pub async fn get_mod_log(
|
||||||
}
|
}
|
||||||
_ => Default::default(),
|
_ => Default::default(),
|
||||||
},
|
},
|
||||||
|
match type_ {
|
||||||
|
All | AdminBlockInstance if other_person_id.is_none() => {
|
||||||
|
AdminBlockInstanceView::list(&mut context.pool(), params).await?
|
||||||
|
}
|
||||||
|
_ => Default::default(),
|
||||||
|
},
|
||||||
|
match type_ {
|
||||||
|
All | AdminAllowInstance if other_person_id.is_none() => {
|
||||||
|
AdminAllowInstanceView::list(&mut context.pool(), params).await?
|
||||||
|
}
|
||||||
|
_ => Default::default(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Default::default()
|
||||||
|
@ -183,5 +199,7 @@ pub async fn get_mod_log(
|
||||||
admin_purged_posts,
|
admin_purged_posts,
|
||||||
admin_purged_comments,
|
admin_purged_comments,
|
||||||
hidden_communities,
|
hidden_communities,
|
||||||
|
admin_block_instance,
|
||||||
|
admin_allow_instance,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{AdminPurgeComment, AdminPurgeCommentForm},
|
mod_log::admin::{AdminPurgeComment, AdminPurgeCommentForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::Community,
|
community::Community,
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{AdminPurgeCommunity, AdminPurgeCommunityForm},
|
mod_log::admin::{AdminPurgeCommunity, AdminPurgeCommunityForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{AdminPurgePerson, AdminPurgePersonForm},
|
mod_log::admin::{AdminPurgePerson, AdminPurgePersonForm},
|
||||||
person::{Person, PersonUpdateForm},
|
person::{Person, PersonUpdateForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
|
|
|
@ -11,7 +11,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{AdminPurgePost, AdminPurgePostForm},
|
mod_log::admin::{AdminPurgePost, AdminPurgePostForm},
|
||||||
post::Post,
|
post::Post,
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
use actix_web::web::Json;
|
use actix_web::web::Json;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{context::LemmyContext, site::UserBlockInstanceParams, SuccessResponse};
|
||||||
context::LemmyContext,
|
|
||||||
site::{BlockInstance, BlockInstanceResponse},
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::instance_block::{InstanceBlock, InstanceBlockForm},
|
source::instance_block::{InstanceBlock, InstanceBlockForm},
|
||||||
traits::Blockable,
|
traits::Blockable,
|
||||||
|
@ -12,11 +9,11 @@ use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||||
|
|
||||||
#[tracing::instrument(skip(context))]
|
#[tracing::instrument(skip(context))]
|
||||||
pub async fn block_instance(
|
pub async fn user_block_instance(
|
||||||
data: Json<BlockInstance>,
|
data: Json<UserBlockInstanceParams>,
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
) -> LemmyResult<Json<BlockInstanceResponse>> {
|
) -> LemmyResult<Json<SuccessResponse>> {
|
||||||
let instance_id = data.instance_id;
|
let instance_id = data.instance_id;
|
||||||
let person_id = local_user_view.person.id;
|
let person_id = local_user_view.person.id;
|
||||||
if local_user_view.person.instance_id == instance_id {
|
if local_user_view.person.instance_id == instance_id {
|
||||||
|
@ -38,7 +35,5 @@ pub async fn block_instance(
|
||||||
.with_lemmy_type(LemmyErrorType::InstanceBlockAlreadyExists)?;
|
.with_lemmy_type(LemmyErrorType::InstanceBlockAlreadyExists)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Json(BlockInstanceResponse {
|
Ok(Json(SuccessResponse::default()))
|
||||||
blocked: data.block,
|
|
||||||
}))
|
|
||||||
}
|
}
|
|
@ -43,6 +43,8 @@ use lemmy_db_views_actor::structs::{
|
||||||
PersonView,
|
PersonView,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_moderator::structs::{
|
use lemmy_db_views_moderator::structs::{
|
||||||
|
AdminAllowInstanceView,
|
||||||
|
AdminBlockInstanceView,
|
||||||
AdminPurgeCommentView,
|
AdminPurgeCommentView,
|
||||||
AdminPurgeCommunityView,
|
AdminPurgeCommunityView,
|
||||||
AdminPurgePersonView,
|
AdminPurgePersonView,
|
||||||
|
@ -183,6 +185,8 @@ pub struct GetModlogResponse {
|
||||||
pub admin_purged_posts: Vec<AdminPurgePostView>,
|
pub admin_purged_posts: Vec<AdminPurgePostView>,
|
||||||
pub admin_purged_comments: Vec<AdminPurgeCommentView>,
|
pub admin_purged_comments: Vec<AdminPurgeCommentView>,
|
||||||
pub hidden_communities: Vec<ModHideCommunityView>,
|
pub hidden_communities: Vec<ModHideCommunityView>,
|
||||||
|
pub admin_block_instance: Vec<AdminBlockInstanceView>,
|
||||||
|
pub admin_allow_instance: Vec<AdminAllowInstanceView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -265,10 +269,6 @@ pub struct CreateSite {
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub captcha_difficulty: Option<String>,
|
pub captcha_difficulty: Option<String>,
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub allowed_instances: Option<Vec<String>>,
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub blocked_instances: Option<Vec<String>>,
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub oauth_registration: Option<bool>,
|
pub oauth_registration: Option<bool>,
|
||||||
|
@ -394,12 +394,6 @@ pub struct EditSite {
|
||||||
/// The captcha difficulty. Can be easy, medium, or hard
|
/// The captcha difficulty. Can be easy, medium, or hard
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub captcha_difficulty: Option<String>,
|
pub captcha_difficulty: Option<String>,
|
||||||
/// A list of allowed instances. If none are set, federation is open.
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub allowed_instances: Option<Vec<String>>,
|
|
||||||
/// A list of blocked instances.
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub blocked_instances: Option<Vec<String>>,
|
|
||||||
/// A list of blocked URLs
|
/// A list of blocked URLs
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub blocked_urls: Option<Vec<String>>,
|
pub blocked_urls: Option<Vec<String>>,
|
||||||
|
@ -644,15 +638,29 @@ pub struct GetUnreadRegistrationApplicationCountResponse {
|
||||||
#[cfg_attr(feature = "full", derive(TS))]
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Block an instance as user
|
/// Block an instance as user
|
||||||
pub struct BlockInstance {
|
pub struct UserBlockInstanceParams {
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
pub block: bool,
|
pub block: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
#[cfg_attr(feature = "full", derive(TS))]
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
pub struct BlockInstanceResponse {
|
pub struct AdminBlockInstanceParams {
|
||||||
pub blocked: bool,
|
pub instance: String,
|
||||||
|
pub block: bool,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct AdminAllowInstanceParams {
|
||||||
|
pub instance: String,
|
||||||
|
pub allow: bool,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,12 @@ use lemmy_db_schema::{
|
||||||
local_site::LocalSite,
|
local_site::LocalSite,
|
||||||
local_site_rate_limit::LocalSiteRateLimit,
|
local_site_rate_limit::LocalSiteRateLimit,
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
moderator::{ModRemoveComment, ModRemoveCommentForm, ModRemovePost, ModRemovePostForm},
|
mod_log::moderator::{
|
||||||
|
ModRemoveComment,
|
||||||
|
ModRemoveCommentForm,
|
||||||
|
ModRemovePost,
|
||||||
|
ModRemovePostForm,
|
||||||
|
},
|
||||||
oauth_account::OAuthAccount,
|
oauth_account::OAuthAccount,
|
||||||
password_reset_request::PasswordResetRequest,
|
password_reset_request::PasswordResetRequest,
|
||||||
person::{Person, PersonUpdateForm},
|
person::{Person, PersonUpdateForm},
|
||||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
||||||
comment::{Comment, CommentUpdateForm},
|
comment::{Comment, CommentUpdateForm},
|
||||||
comment_report::CommentReport,
|
comment_report::CommentReport,
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{ModRemoveComment, ModRemoveCommentForm},
|
mod_log::moderator::{ModRemoveComment, ModRemoveCommentForm},
|
||||||
},
|
},
|
||||||
traits::{Crud, Reportable},
|
traits::{Crud, Reportable},
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::{Community, CommunityUpdateForm},
|
community::{Community, CommunityUpdateForm},
|
||||||
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
|
mod_log::moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::Community,
|
community::Community,
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
moderator::{ModRemovePost, ModRemovePostForm},
|
mod_log::moderator::{ModRemovePost, ModRemovePostForm},
|
||||||
post::{Post, PostUpdateForm},
|
post::{Post, PostUpdateForm},
|
||||||
post_report::PostReport,
|
post_report::PostReport,
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,8 +19,6 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
actor_language::SiteLanguage,
|
actor_language::SiteLanguage,
|
||||||
federation_allowlist::FederationAllowList,
|
|
||||||
federation_blocklist::FederationBlockList,
|
|
||||||
local_site::{LocalSite, LocalSiteUpdateForm},
|
local_site::{LocalSite, LocalSiteUpdateForm},
|
||||||
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
|
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
|
@ -152,12 +150,6 @@ pub async fn update_site(
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
// Replace the blocked and allowed instances
|
|
||||||
let allowed = data.allowed_instances.clone();
|
|
||||||
FederationAllowList::replace(&mut context.pool(), allowed).await?;
|
|
||||||
let blocked = data.blocked_instances.clone();
|
|
||||||
FederationBlockList::replace(&mut context.pool(), blocked).await?;
|
|
||||||
|
|
||||||
if let Some(url_blocklist) = data.blocked_urls.clone() {
|
if let Some(url_blocklist) = data.blocked_urls.clone() {
|
||||||
let parsed_urls = check_urls_are_valid(&url_blocklist)?;
|
let parsed_urls = check_urls_are_valid(&url_blocklist)?;
|
||||||
LocalSiteUrlBlocklist::replace(&mut context.pool(), parsed_urls).await?;
|
LocalSiteUrlBlocklist::replace(&mut context.pool(), parsed_urls).await?;
|
||||||
|
|
|
@ -21,8 +21,9 @@ use lemmy_api_common::{
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
aggregates::structs::PersonAggregates,
|
aggregates::structs::PersonAggregates,
|
||||||
newtypes::{InstanceId, OAuthProviderId},
|
newtypes::{InstanceId, OAuthProviderId, SiteId},
|
||||||
source::{
|
source::{
|
||||||
|
actor_language::SiteLanguage,
|
||||||
captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer},
|
captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer},
|
||||||
language::Language,
|
language::Language,
|
||||||
local_site::LocalSite,
|
local_site::LocalSite,
|
||||||
|
@ -145,7 +146,13 @@ pub async fn register(
|
||||||
..LocalUserInsertForm::new(inserted_person.id, Some(data.password.to_string()))
|
..LocalUserInsertForm::new(inserted_person.id, Some(data.password.to_string()))
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_local_user = create_local_user(&context, language_tags, &local_user_form).await?;
|
let inserted_local_user = create_local_user(
|
||||||
|
&context,
|
||||||
|
language_tags,
|
||||||
|
&local_user_form,
|
||||||
|
local_site.site_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if local_site.site_setup && require_registration_application {
|
if local_site.site_setup && require_registration_application {
|
||||||
if let Some(answer) = data.answer.clone() {
|
if let Some(answer) = data.answer.clone() {
|
||||||
|
@ -358,7 +365,13 @@ pub async fn authenticate_with_oauth(
|
||||||
..LocalUserInsertForm::new(person.id, None)
|
..LocalUserInsertForm::new(person.id, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
local_user = create_local_user(&context, language_tags, &local_user_form).await?;
|
local_user = create_local_user(
|
||||||
|
&context,
|
||||||
|
language_tags,
|
||||||
|
&local_user_form,
|
||||||
|
local_site.site_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Create the oauth account
|
// Create the oauth account
|
||||||
let oauth_account_form =
|
let oauth_account_form =
|
||||||
|
@ -449,15 +462,23 @@ async fn create_local_user(
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
language_tags: Vec<String>,
|
language_tags: Vec<String>,
|
||||||
local_user_form: &LocalUserInsertForm,
|
local_user_form: &LocalUserInsertForm,
|
||||||
|
local_site_id: SiteId,
|
||||||
) -> Result<LocalUser, LemmyError> {
|
) -> Result<LocalUser, LemmyError> {
|
||||||
let all_languages = Language::read_all(&mut context.pool()).await?;
|
let all_languages = Language::read_all(&mut context.pool()).await?;
|
||||||
// use hashset to avoid duplicates
|
// use hashset to avoid duplicates
|
||||||
let mut language_ids = HashSet::new();
|
let mut language_ids = HashSet::new();
|
||||||
|
|
||||||
|
// Enable languages from `Accept-Language` header
|
||||||
for l in language_tags {
|
for l in language_tags {
|
||||||
if let Some(found) = all_languages.iter().find(|all| all.code == l) {
|
if let Some(found) = all_languages.iter().find(|all| all.code == l) {
|
||||||
language_ids.insert(found.id);
|
language_ids.insert(found.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable site languages. Ignored if all languages are enabled.
|
||||||
|
let discussion_languages = SiteLanguage::read(&mut context.pool(), local_site_id).await?;
|
||||||
|
language_ids.extend(discussion_languages);
|
||||||
|
|
||||||
let language_ids = language_ids.into_iter().collect();
|
let language_ids = language_ids.into_iter().collect();
|
||||||
|
|
||||||
let inserted_local_user =
|
let inserted_local_user =
|
||||||
|
|
|
@ -36,7 +36,7 @@ use lemmy_db_schema::{
|
||||||
CommunityPersonBan,
|
CommunityPersonBan,
|
||||||
CommunityPersonBanForm,
|
CommunityPersonBanForm,
|
||||||
},
|
},
|
||||||
moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
mod_log::moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
||||||
person::{Person, PersonUpdateForm},
|
person::{Person, PersonUpdateForm},
|
||||||
},
|
},
|
||||||
traits::{Bannable, Crud, Followable},
|
traits::{Bannable, Crud, Followable},
|
||||||
|
|
|
@ -27,7 +27,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
activity::ActivitySendTargets,
|
activity::ActivitySendTargets,
|
||||||
community::{CommunityPersonBan, CommunityPersonBanForm},
|
community::{CommunityPersonBan, CommunityPersonBanForm},
|
||||||
moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
mod_log::moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
||||||
person::{Person, PersonUpdateForm},
|
person::{Person, PersonUpdateForm},
|
||||||
},
|
},
|
||||||
traits::{Bannable, Crud},
|
traits::{Bannable, Crud},
|
||||||
|
|
|
@ -31,7 +31,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
activity::ActivitySendTargets,
|
activity::ActivitySendTargets,
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||||
moderator::{ModAddCommunity, ModAddCommunityForm},
|
mod_log::moderator::{ModAddCommunity, ModAddCommunityForm},
|
||||||
person::Person,
|
person::Person,
|
||||||
post::{Post, PostUpdateForm},
|
post::{Post, PostUpdateForm},
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,7 +27,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
activity::ActivitySendTargets,
|
activity::ActivitySendTargets,
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||||
moderator::{ModAddCommunity, ModAddCommunityForm},
|
mod_log::moderator::{ModAddCommunity, ModAddCommunityForm},
|
||||||
post::{Post, PostUpdateForm},
|
post::{Post, PostUpdateForm},
|
||||||
},
|
},
|
||||||
traits::{Crud, Joinable},
|
traits::{Crud, Joinable},
|
||||||
|
|
|
@ -27,7 +27,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
activity::ActivitySendTargets,
|
activity::ActivitySendTargets,
|
||||||
community::Community,
|
community::Community,
|
||||||
moderator::{ModLockPost, ModLockPostForm},
|
mod_log::moderator::{ModLockPost, ModLockPostForm},
|
||||||
person::Person,
|
person::Person,
|
||||||
post::{Post, PostUpdateForm},
|
post::{Post, PostUpdateForm},
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ use lemmy_db_schema::{
|
||||||
comment::{Comment, CommentUpdateForm},
|
comment::{Comment, CommentUpdateForm},
|
||||||
comment_report::CommentReport,
|
comment_report::CommentReport,
|
||||||
community::{Community, CommunityUpdateForm},
|
community::{Community, CommunityUpdateForm},
|
||||||
moderator::{
|
mod_log::moderator::{
|
||||||
ModRemoveComment,
|
ModRemoveComment,
|
||||||
ModRemoveCommentForm,
|
ModRemoveCommentForm,
|
||||||
ModRemoveCommunity,
|
ModRemoveCommunity,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentUpdateForm},
|
comment::{Comment, CommentUpdateForm},
|
||||||
community::{Community, CommunityUpdateForm},
|
community::{Community, CommunityUpdateForm},
|
||||||
moderator::{
|
mod_log::moderator::{
|
||||||
ModRemoveComment,
|
ModRemoveComment,
|
||||||
ModRemoveCommentForm,
|
ModRemoveCommentForm,
|
||||||
ModRemoveCommunity,
|
ModRemoveCommunity,
|
||||||
|
|
|
@ -322,7 +322,7 @@ pub(crate) mod tests {
|
||||||
CommunityFollowerState,
|
CommunityFollowerState,
|
||||||
CommunityInsertForm,
|
CommunityInsertForm,
|
||||||
},
|
},
|
||||||
local_user::LocalUser,
|
person::Person,
|
||||||
},
|
},
|
||||||
traits::{Crud, Followable},
|
traits::{Crud, Followable},
|
||||||
};
|
};
|
||||||
|
@ -376,8 +376,8 @@ pub(crate) mod tests {
|
||||||
assert_eq!(follows.len(), 1);
|
assert_eq!(follows.len(), 1);
|
||||||
assert_eq!(follows[0].community.actor_id, community.actor_id);
|
assert_eq!(follows[0].community.actor_id, community.actor_id);
|
||||||
|
|
||||||
LocalUser::delete(pool, export_user.local_user.id).await?;
|
Person::delete(pool, export_user.person.id).await?;
|
||||||
LocalUser::delete(pool, import_user.local_user.id).await?;
|
Person::delete(pool, import_user.person.id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,8 +412,8 @@ pub(crate) mod tests {
|
||||||
Some(LemmyErrorType::TooManyItems)
|
Some(LemmyErrorType::TooManyItems)
|
||||||
);
|
);
|
||||||
|
|
||||||
LocalUser::delete(pool, export_user.local_user.id).await?;
|
Person::delete(pool, export_user.person.id).await?;
|
||||||
LocalUser::delete(pool, import_user.local_user.id).await?;
|
Person::delete(pool, import_user.person.id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,60 +1,51 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::federation_allowlist,
|
newtypes::InstanceId,
|
||||||
|
schema::{admin_allow_instance, federation_allowlist},
|
||||||
source::{
|
source::{
|
||||||
federation_allowlist::{FederationAllowList, FederationAllowListForm},
|
federation_allowlist::{FederationAllowList, FederationAllowListForm},
|
||||||
instance::Instance,
|
mod_log::admin::{AdminAllowInstance, AdminAllowInstanceForm},
|
||||||
},
|
},
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
use diesel::{dsl::insert_into, result::Error};
|
use diesel::{delete, dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||||
use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
impl FederationAllowList {
|
impl AdminAllowInstance {
|
||||||
pub async fn replace(pool: &mut DbPool<'_>, list_opt: Option<Vec<String>>) -> Result<(), Error> {
|
pub async fn insert(pool: &mut DbPool<'_>, form: &AdminAllowInstanceForm) -> Result<(), Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
conn
|
insert_into(admin_allow_instance::table)
|
||||||
.build_transaction()
|
.values(form)
|
||||||
.run(|conn| {
|
|
||||||
Box::pin(async move {
|
|
||||||
if let Some(list) = list_opt {
|
|
||||||
Self::clear(conn).await?;
|
|
||||||
|
|
||||||
for domain in list {
|
|
||||||
// Upsert all of these as instances
|
|
||||||
let instance = Instance::read_or_create(&mut conn.into(), domain).await?;
|
|
||||||
|
|
||||||
let form = FederationAllowListForm {
|
|
||||||
instance_id: instance.id,
|
|
||||||
updated: None,
|
|
||||||
};
|
|
||||||
insert_into(federation_allowlist::table)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}) as _
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
|
|
||||||
diesel::delete(federation_allowlist::table)
|
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FederationAllowList {
|
||||||
|
pub async fn allow(pool: &mut DbPool<'_>, form: &FederationAllowListForm) -> Result<(), Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
insert_into(federation_allowlist::table)
|
||||||
|
.values(form)
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub async fn unallow(pool: &mut DbPool<'_>, instance_id_: InstanceId) -> Result<(), Error> {
|
||||||
|
use federation_allowlist::dsl::instance_id;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
delete(federation_allowlist::table.filter(instance_id.eq(instance_id_)))
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use crate::{
|
use super::*;
|
||||||
source::{federation_allowlist::FederationAllowList, instance::Instance},
|
use crate::{source::instance::Instance, utils::build_db_pool_for_tests};
|
||||||
utils::build_db_pool_for_tests,
|
|
||||||
};
|
|
||||||
use diesel::result::Error;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -63,31 +54,33 @@ mod tests {
|
||||||
async fn test_allowlist_insert_and_clear() -> Result<(), Error> {
|
async fn test_allowlist_insert_and_clear() -> Result<(), Error> {
|
||||||
let pool = &build_db_pool_for_tests();
|
let pool = &build_db_pool_for_tests();
|
||||||
let pool = &mut pool.into();
|
let pool = &mut pool.into();
|
||||||
let domains = vec![
|
let instances = vec![
|
||||||
"tld1.xyz".to_string(),
|
Instance::read_or_create(pool, "tld1.xyz".to_string()).await?,
|
||||||
"tld2.xyz".to_string(),
|
Instance::read_or_create(pool, "tld2.xyz".to_string()).await?,
|
||||||
"tld3.xyz".to_string(),
|
Instance::read_or_create(pool, "tld3.xyz".to_string()).await?,
|
||||||
];
|
];
|
||||||
|
let forms: Vec<_> = instances
|
||||||
|
.iter()
|
||||||
|
.map(|i| FederationAllowListForm {
|
||||||
|
instance_id: i.id,
|
||||||
|
updated: None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let allowed = Some(domains.clone());
|
for f in &forms {
|
||||||
|
FederationAllowList::allow(pool, f).await?;
|
||||||
FederationAllowList::replace(pool, allowed).await?;
|
}
|
||||||
|
|
||||||
let allows = Instance::allowlist(pool).await?;
|
let allows = Instance::allowlist(pool).await?;
|
||||||
let allows_domains = allows
|
|
||||||
.iter()
|
|
||||||
.map(|i| i.domain.clone())
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
|
|
||||||
assert_eq!(3, allows.len());
|
assert_eq!(3, allows.len());
|
||||||
assert_eq!(domains, allows_domains);
|
assert_eq!(instances, allows);
|
||||||
|
|
||||||
// Now test clearing them via Some(empty vec)
|
// Now test clearing them
|
||||||
let clear_allows = Some(Vec::new());
|
for f in forms {
|
||||||
|
FederationAllowList::unallow(pool, f.instance_id).await?;
|
||||||
FederationAllowList::replace(pool, clear_allows).await?;
|
}
|
||||||
let allows = Instance::allowlist(pool).await?;
|
let allows = Instance::allowlist(pool).await?;
|
||||||
|
|
||||||
assert_eq!(0, allows.len());
|
assert_eq!(0, allows.len());
|
||||||
|
|
||||||
Instance::delete_all(pool).await?;
|
Instance::delete_all(pool).await?;
|
||||||
|
|
|
@ -1,49 +1,42 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::federation_blocklist,
|
newtypes::InstanceId,
|
||||||
|
schema::{admin_block_instance, federation_blocklist},
|
||||||
source::{
|
source::{
|
||||||
federation_blocklist::{FederationBlockList, FederationBlockListForm},
|
federation_blocklist::{FederationBlockList, FederationBlockListForm},
|
||||||
instance::Instance,
|
mod_log::admin::{AdminBlockInstance, AdminBlockInstanceForm},
|
||||||
},
|
},
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
use diesel::{dsl::insert_into, result::Error};
|
use diesel::{delete, dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||||
use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
impl FederationBlockList {
|
impl AdminBlockInstance {
|
||||||
pub async fn replace(pool: &mut DbPool<'_>, list_opt: Option<Vec<String>>) -> Result<(), Error> {
|
pub async fn insert(pool: &mut DbPool<'_>, form: &AdminBlockInstanceForm) -> Result<(), Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
conn
|
insert_into(admin_block_instance::table)
|
||||||
.build_transaction()
|
.values(form)
|
||||||
.run(|conn| {
|
|
||||||
Box::pin(async move {
|
|
||||||
if let Some(list) = list_opt {
|
|
||||||
Self::clear(conn).await?;
|
|
||||||
|
|
||||||
for domain in list {
|
|
||||||
// Upsert all of these as instances
|
|
||||||
let instance = Instance::read_or_create(&mut conn.into(), domain).await?;
|
|
||||||
|
|
||||||
let form = FederationBlockListForm {
|
|
||||||
instance_id: instance.id,
|
|
||||||
updated: None,
|
|
||||||
};
|
|
||||||
insert_into(federation_blocklist::table)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}) as _
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
|
|
||||||
diesel::delete(federation_blocklist::table)
|
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FederationBlockList {
|
||||||
|
pub async fn block(pool: &mut DbPool<'_>, form: &FederationBlockListForm) -> Result<(), Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
insert_into(federation_blocklist::table)
|
||||||
|
.values(form)
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub async fn unblock(pool: &mut DbPool<'_>, instance_id_: InstanceId) -> Result<(), Error> {
|
||||||
|
use federation_blocklist::dsl::instance_id;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
delete(federation_blocklist::table.filter(instance_id.eq(instance_id_)))
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub mod local_site_url_blocklist;
|
||||||
pub mod local_user;
|
pub mod local_user;
|
||||||
pub mod local_user_vote_display_mode;
|
pub mod local_user_vote_display_mode;
|
||||||
pub mod login_token;
|
pub mod login_token;
|
||||||
pub mod moderator;
|
pub mod mod_log;
|
||||||
pub mod oauth_account;
|
pub mod oauth_account;
|
||||||
pub mod oauth_provider;
|
pub mod oauth_provider;
|
||||||
pub mod password_reset_request;
|
pub mod password_reset_request;
|
||||||
|
|
132
crates/db_schema/src/impls/mod_log/admin.rs
Normal file
132
crates/db_schema/src/impls/mod_log/admin.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
use crate::{
|
||||||
|
source::mod_log::admin::{
|
||||||
|
AdminPurgeComment,
|
||||||
|
AdminPurgeCommentForm,
|
||||||
|
AdminPurgeCommunity,
|
||||||
|
AdminPurgeCommunityForm,
|
||||||
|
AdminPurgePerson,
|
||||||
|
AdminPurgePersonForm,
|
||||||
|
AdminPurgePost,
|
||||||
|
AdminPurgePostForm,
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
utils::{get_conn, DbPool},
|
||||||
|
};
|
||||||
|
use diesel::{dsl::insert_into, result::Error, QueryDsl};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Crud for AdminPurgePerson {
|
||||||
|
type InsertForm = AdminPurgePersonForm;
|
||||||
|
type UpdateForm = AdminPurgePersonForm;
|
||||||
|
type IdType = i32;
|
||||||
|
|
||||||
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_person::dsl::admin_purge_person;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
insert_into(admin_purge_person)
|
||||||
|
.values(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
from_id: i32,
|
||||||
|
form: &Self::InsertForm,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_person::dsl::admin_purge_person;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
diesel::update(admin_purge_person.find(from_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Crud for AdminPurgeCommunity {
|
||||||
|
type InsertForm = AdminPurgeCommunityForm;
|
||||||
|
type UpdateForm = AdminPurgeCommunityForm;
|
||||||
|
type IdType = i32;
|
||||||
|
|
||||||
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_community::dsl::admin_purge_community;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
insert_into(admin_purge_community)
|
||||||
|
.values(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
from_id: i32,
|
||||||
|
form: &Self::InsertForm,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_community::dsl::admin_purge_community;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
diesel::update(admin_purge_community.find(from_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Crud for AdminPurgePost {
|
||||||
|
type InsertForm = AdminPurgePostForm;
|
||||||
|
type UpdateForm = AdminPurgePostForm;
|
||||||
|
type IdType = i32;
|
||||||
|
|
||||||
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_post::dsl::admin_purge_post;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
insert_into(admin_purge_post)
|
||||||
|
.values(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
from_id: i32,
|
||||||
|
form: &Self::InsertForm,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_post::dsl::admin_purge_post;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
diesel::update(admin_purge_post.find(from_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Crud for AdminPurgeComment {
|
||||||
|
type InsertForm = AdminPurgeCommentForm;
|
||||||
|
type UpdateForm = AdminPurgeCommentForm;
|
||||||
|
type IdType = i32;
|
||||||
|
|
||||||
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_comment::dsl::admin_purge_comment;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
insert_into(admin_purge_comment)
|
||||||
|
.values(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
from_id: i32,
|
||||||
|
form: &Self::InsertForm,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::admin_purge_comment::dsl::admin_purge_comment;
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
diesel::update(admin_purge_comment.find(from_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
2
crates/db_schema/src/impls/mod_log/mod.rs
Normal file
2
crates/db_schema/src/impls/mod_log/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod admin;
|
||||||
|
pub mod moderator;
|
|
@ -1,13 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
source::moderator::{
|
source::mod_log::moderator::{
|
||||||
AdminPurgeComment,
|
|
||||||
AdminPurgeCommentForm,
|
|
||||||
AdminPurgeCommunity,
|
|
||||||
AdminPurgeCommunityForm,
|
|
||||||
AdminPurgePerson,
|
|
||||||
AdminPurgePersonForm,
|
|
||||||
AdminPurgePost,
|
|
||||||
AdminPurgePostForm,
|
|
||||||
ModAdd,
|
ModAdd,
|
||||||
ModAddCommunity,
|
ModAddCommunity,
|
||||||
ModAddCommunityForm,
|
ModAddCommunityForm,
|
||||||
|
@ -376,157 +368,20 @@ impl Crud for ModAdd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Crud for AdminPurgePerson {
|
|
||||||
type InsertForm = AdminPurgePersonForm;
|
|
||||||
type UpdateForm = AdminPurgePersonForm;
|
|
||||||
type IdType = i32;
|
|
||||||
|
|
||||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_person::dsl::admin_purge_person;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
insert_into(admin_purge_person)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn update(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
from_id: i32,
|
|
||||||
form: &Self::InsertForm,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_person::dsl::admin_purge_person;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
diesel::update(admin_purge_person.find(from_id))
|
|
||||||
.set(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Crud for AdminPurgeCommunity {
|
|
||||||
type InsertForm = AdminPurgeCommunityForm;
|
|
||||||
type UpdateForm = AdminPurgeCommunityForm;
|
|
||||||
type IdType = i32;
|
|
||||||
|
|
||||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_community::dsl::admin_purge_community;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
insert_into(admin_purge_community)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn update(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
from_id: i32,
|
|
||||||
form: &Self::InsertForm,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_community::dsl::admin_purge_community;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
diesel::update(admin_purge_community.find(from_id))
|
|
||||||
.set(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Crud for AdminPurgePost {
|
|
||||||
type InsertForm = AdminPurgePostForm;
|
|
||||||
type UpdateForm = AdminPurgePostForm;
|
|
||||||
type IdType = i32;
|
|
||||||
|
|
||||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_post::dsl::admin_purge_post;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
insert_into(admin_purge_post)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn update(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
from_id: i32,
|
|
||||||
form: &Self::InsertForm,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_post::dsl::admin_purge_post;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
diesel::update(admin_purge_post.find(from_id))
|
|
||||||
.set(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Crud for AdminPurgeComment {
|
|
||||||
type InsertForm = AdminPurgeCommentForm;
|
|
||||||
type UpdateForm = AdminPurgeCommentForm;
|
|
||||||
type IdType = i32;
|
|
||||||
|
|
||||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_comment::dsl::admin_purge_comment;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
insert_into(admin_purge_comment)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn update(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
from_id: i32,
|
|
||||||
form: &Self::InsertForm,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
use crate::schema::admin_purge_comment::dsl::admin_purge_comment;
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
diesel::update(admin_purge_comment.find(from_id))
|
|
||||||
.set(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentInsertForm},
|
comment::{Comment, CommentInsertForm},
|
||||||
community::{Community, CommunityInsertForm},
|
community::{Community, CommunityInsertForm},
|
||||||
instance::Instance,
|
instance::Instance,
|
||||||
moderator::{
|
|
||||||
ModAdd,
|
|
||||||
ModAddCommunity,
|
|
||||||
ModAddCommunityForm,
|
|
||||||
ModAddForm,
|
|
||||||
ModBan,
|
|
||||||
ModBanForm,
|
|
||||||
ModBanFromCommunity,
|
|
||||||
ModBanFromCommunityForm,
|
|
||||||
ModFeaturePost,
|
|
||||||
ModFeaturePostForm,
|
|
||||||
ModLockPost,
|
|
||||||
ModLockPostForm,
|
|
||||||
ModRemoveComment,
|
|
||||||
ModRemoveCommentForm,
|
|
||||||
ModRemoveCommunity,
|
|
||||||
ModRemoveCommunityForm,
|
|
||||||
ModRemovePost,
|
|
||||||
ModRemovePostForm,
|
|
||||||
},
|
|
||||||
person::{Person, PersonInsertForm},
|
person::{Person, PersonInsertForm},
|
||||||
post::{Post, PostInsertForm},
|
post::{Post, PostInsertForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
|
||||||
utils::build_db_pool_for_tests,
|
utils::build_db_pool_for_tests,
|
||||||
};
|
};
|
||||||
use diesel::result::Error;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
|
@ -215,6 +215,8 @@ pub enum ModlogActionType {
|
||||||
AdminPurgeCommunity,
|
AdminPurgeCommunity,
|
||||||
AdminPurgePost,
|
AdminPurgePost,
|
||||||
AdminPurgeComment,
|
AdminPurgeComment,
|
||||||
|
AdminBlockInstance,
|
||||||
|
AdminAllowInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
|
@ -42,6 +42,29 @@ pub mod sql_types {
|
||||||
pub struct RegistrationModeEnum;
|
pub struct RegistrationModeEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
admin_allow_instance (id) {
|
||||||
|
id -> Int4,
|
||||||
|
instance_id -> Int4,
|
||||||
|
admin_person_id -> Int4,
|
||||||
|
allowed -> Bool,
|
||||||
|
reason -> Nullable<Text>,
|
||||||
|
when_ -> Timestamptz,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
admin_block_instance (id) {
|
||||||
|
id -> Int4,
|
||||||
|
instance_id -> Int4,
|
||||||
|
admin_person_id -> Int4,
|
||||||
|
blocked -> Bool,
|
||||||
|
reason -> Nullable<Text>,
|
||||||
|
expires -> Nullable<Timestamptz>,
|
||||||
|
when_ -> Timestamptz,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
admin_purge_comment (id) {
|
admin_purge_comment (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
|
@ -284,6 +307,7 @@ diesel::table! {
|
||||||
instance_id -> Int4,
|
instance_id -> Int4,
|
||||||
published -> Timestamptz,
|
published -> Timestamptz,
|
||||||
updated -> Nullable<Timestamptz>,
|
updated -> Nullable<Timestamptz>,
|
||||||
|
expires -> Nullable<Timestamptz>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,6 +959,10 @@ diesel::table! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::joinable!(admin_allow_instance -> instance (instance_id));
|
||||||
|
diesel::joinable!(admin_allow_instance -> person (admin_person_id));
|
||||||
|
diesel::joinable!(admin_block_instance -> instance (instance_id));
|
||||||
|
diesel::joinable!(admin_block_instance -> person (admin_person_id));
|
||||||
diesel::joinable!(admin_purge_comment -> person (admin_person_id));
|
diesel::joinable!(admin_purge_comment -> person (admin_person_id));
|
||||||
diesel::joinable!(admin_purge_comment -> post (post_id));
|
diesel::joinable!(admin_purge_comment -> post (post_id));
|
||||||
diesel::joinable!(admin_purge_community -> person (admin_person_id));
|
diesel::joinable!(admin_purge_community -> person (admin_person_id));
|
||||||
|
@ -1012,6 +1040,8 @@ diesel::joinable!(site_language -> language (language_id));
|
||||||
diesel::joinable!(site_language -> site (site_id));
|
diesel::joinable!(site_language -> site (site_id));
|
||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
|
admin_allow_instance,
|
||||||
|
admin_block_instance,
|
||||||
admin_purge_comment,
|
admin_purge_comment,
|
||||||
admin_purge_community,
|
admin_purge_community,
|
||||||
admin_purge_person,
|
admin_purge_person,
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use crate::newtypes::InstanceId;
|
use crate::newtypes::InstanceId;
|
||||||
#[cfg(feature = "full")]
|
|
||||||
use crate::schema::federation_blocklist;
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
use {crate::schema::federation_blocklist, ts_rs::TS};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "full",
|
feature = "full",
|
||||||
derive(Queryable, Selectable, Associations, Identifiable)
|
derive(TS, Queryable, Selectable, Associations, Identifiable)
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "full",
|
feature = "full",
|
||||||
|
@ -17,10 +17,14 @@ use std::fmt::Debug;
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = federation_blocklist))]
|
#[cfg_attr(feature = "full", diesel(table_name = federation_blocklist))]
|
||||||
#[cfg_attr(feature = "full", diesel(primary_key(instance_id)))]
|
#[cfg_attr(feature = "full", diesel(primary_key(instance_id)))]
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
pub struct FederationBlockList {
|
pub struct FederationBlockList {
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub updated: Option<DateTime<Utc>>,
|
pub updated: Option<DateTime<Utc>>,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
@ -29,4 +33,5 @@ pub struct FederationBlockList {
|
||||||
pub struct FederationBlockListForm {
|
pub struct FederationBlockListForm {
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
pub updated: Option<DateTime<Utc>>,
|
pub updated: Option<DateTime<Utc>>,
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub mod local_site_url_blocklist;
|
||||||
pub mod local_user;
|
pub mod local_user;
|
||||||
pub mod local_user_vote_display_mode;
|
pub mod local_user_vote_display_mode;
|
||||||
pub mod login_token;
|
pub mod login_token;
|
||||||
pub mod moderator;
|
pub mod mod_log;
|
||||||
pub mod oauth_account;
|
pub mod oauth_account;
|
||||||
pub mod oauth_provider;
|
pub mod oauth_provider;
|
||||||
pub mod password_reset_request;
|
pub mod password_reset_request;
|
||||||
|
|
176
crates/db_schema/src/source/mod_log/admin.rs
Normal file
176
crates/db_schema/src/source/mod_log/admin.rs
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
use crate::newtypes::{CommunityId, InstanceId, PersonId, PostId};
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
use crate::schema::{
|
||||||
|
admin_allow_instance,
|
||||||
|
admin_block_instance,
|
||||||
|
admin_purge_comment,
|
||||||
|
admin_purge_community,
|
||||||
|
admin_purge_person,
|
||||||
|
admin_purge_post,
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::skip_serializing_none;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
use ts_rs::TS;
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_person))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a person.
|
||||||
|
pub struct AdminPurgePerson {
|
||||||
|
pub id: i32,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub when_: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_person))]
|
||||||
|
pub struct AdminPurgePersonForm {
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_community))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a community.
|
||||||
|
pub struct AdminPurgeCommunity {
|
||||||
|
pub id: i32,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub when_: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_community))]
|
||||||
|
pub struct AdminPurgeCommunityForm {
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_post))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a post.
|
||||||
|
pub struct AdminPurgePost {
|
||||||
|
pub id: i32,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub community_id: CommunityId,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub when_: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_post))]
|
||||||
|
pub struct AdminPurgePostForm {
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub community_id: CommunityId,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_comment))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a comment.
|
||||||
|
pub struct AdminPurgeComment {
|
||||||
|
pub id: i32,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub post_id: PostId,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub when_: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_comment))]
|
||||||
|
pub struct AdminPurgeCommentForm {
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub post_id: PostId,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "full",
|
||||||
|
derive(TS, Queryable, Selectable, Associations, Identifiable)
|
||||||
|
)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "full",
|
||||||
|
diesel(belongs_to(crate::source::instance::Instance))
|
||||||
|
)]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_allow_instance))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(primary_key(instance_id)))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct AdminAllowInstance {
|
||||||
|
pub id: i32,
|
||||||
|
pub instance_id: InstanceId,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub allowed: bool,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub when_: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_allow_instance))]
|
||||||
|
pub struct AdminAllowInstanceForm {
|
||||||
|
pub instance_id: InstanceId,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub allowed: bool,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "full",
|
||||||
|
derive(TS, Queryable, Selectable, Associations, Identifiable)
|
||||||
|
)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "full",
|
||||||
|
diesel(belongs_to(crate::source::instance::Instance))
|
||||||
|
)]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_block_instance))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(primary_key(instance_id)))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct AdminBlockInstance {
|
||||||
|
pub id: i32,
|
||||||
|
pub instance_id: InstanceId,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub blocked: bool,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub reason: Option<String>,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
|
pub when_: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = admin_block_instance))]
|
||||||
|
pub struct AdminBlockInstanceForm {
|
||||||
|
pub instance_id: InstanceId,
|
||||||
|
pub admin_person_id: PersonId,
|
||||||
|
pub blocked: bool,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub when_: Option<DateTime<Utc>>,
|
||||||
|
}
|
2
crates/db_schema/src/source/mod_log/mod.rs
Normal file
2
crates/db_schema/src/source/mod_log/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod admin;
|
||||||
|
pub mod moderator;
|
|
@ -1,10 +1,6 @@
|
||||||
use crate::newtypes::{CommentId, CommunityId, PersonId, PostId};
|
use crate::newtypes::{CommentId, CommunityId, PersonId, PostId};
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::{
|
use crate::schema::{
|
||||||
admin_purge_comment,
|
|
||||||
admin_purge_community,
|
|
||||||
admin_purge_person,
|
|
||||||
admin_purge_post,
|
|
||||||
mod_add,
|
mod_add,
|
||||||
mod_add_community,
|
mod_add_community,
|
||||||
mod_ban,
|
mod_ban,
|
||||||
|
@ -300,95 +296,3 @@ pub struct ModAddForm {
|
||||||
pub other_person_id: PersonId,
|
pub other_person_id: PersonId,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_person))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// When an admin purges a person.
|
|
||||||
pub struct AdminPurgePerson {
|
|
||||||
pub id: i32,
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub reason: Option<String>,
|
|
||||||
pub when_: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_person))]
|
|
||||||
pub struct AdminPurgePersonForm {
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
pub reason: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[skip_serializing_none]
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_community))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// When an admin purges a community.
|
|
||||||
pub struct AdminPurgeCommunity {
|
|
||||||
pub id: i32,
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub reason: Option<String>,
|
|
||||||
pub when_: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_community))]
|
|
||||||
pub struct AdminPurgeCommunityForm {
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
pub reason: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[skip_serializing_none]
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_post))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// When an admin purges a post.
|
|
||||||
pub struct AdminPurgePost {
|
|
||||||
pub id: i32,
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
pub community_id: CommunityId,
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub reason: Option<String>,
|
|
||||||
pub when_: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_post))]
|
|
||||||
pub struct AdminPurgePostForm {
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
pub community_id: CommunityId,
|
|
||||||
pub reason: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[skip_serializing_none]
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_comment))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// When an admin purges a comment.
|
|
||||||
pub struct AdminPurgeComment {
|
|
||||||
pub id: i32,
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
pub post_id: PostId,
|
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
|
||||||
pub reason: Option<String>,
|
|
||||||
pub when_: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = admin_purge_comment))]
|
|
||||||
pub struct AdminPurgeCommentForm {
|
|
||||||
pub admin_person_id: PersonId,
|
|
||||||
pub post_id: PostId,
|
|
||||||
pub reason: Option<String>,
|
|
||||||
}
|
|
52
crates/db_views_moderator/src/admin_allow_instance.rs
Normal file
52
crates/db_views_moderator/src/admin_allow_instance.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::structs::{AdminAllowInstanceView, ModlogListParams};
|
||||||
|
use diesel::{
|
||||||
|
result::Error,
|
||||||
|
BoolExpressionMethods,
|
||||||
|
ExpressionMethods,
|
||||||
|
IntoSql,
|
||||||
|
JoinOnDsl,
|
||||||
|
NullableExpressionMethods,
|
||||||
|
QueryDsl,
|
||||||
|
};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
newtypes::PersonId,
|
||||||
|
schema::{admin_allow_instance, instance, person},
|
||||||
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl AdminAllowInstanceView {
|
||||||
|
pub async fn list(pool: &mut DbPool<'_>, params: ModlogListParams) -> Result<Vec<Self>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
|
||||||
|
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
|
||||||
|
let show_mod_names = !params.hide_modlog_names;
|
||||||
|
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
|
||||||
|
|
||||||
|
let admin_names_join = admin_allow_instance::admin_person_id
|
||||||
|
.eq(person::id)
|
||||||
|
.and(show_mod_names_expr.or(person::id.eq(admin_person_id_join)));
|
||||||
|
let mut query = admin_allow_instance::table
|
||||||
|
.left_join(person::table.on(admin_names_join))
|
||||||
|
.inner_join(instance::table)
|
||||||
|
.select((
|
||||||
|
admin_allow_instance::all_columns,
|
||||||
|
instance::all_columns,
|
||||||
|
person::all_columns.nullable(),
|
||||||
|
))
|
||||||
|
.into_boxed();
|
||||||
|
|
||||||
|
if let Some(admin_person_id) = params.mod_person_id {
|
||||||
|
query = query.filter(admin_allow_instance::admin_person_id.eq(admin_person_id));
|
||||||
|
};
|
||||||
|
|
||||||
|
let (limit, offset) = limit_and_offset(params.page, params.limit)?;
|
||||||
|
|
||||||
|
query
|
||||||
|
.limit(limit)
|
||||||
|
.offset(offset)
|
||||||
|
.order_by(admin_allow_instance::when_.desc())
|
||||||
|
.load::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
52
crates/db_views_moderator/src/admin_block_instance.rs
Normal file
52
crates/db_views_moderator/src/admin_block_instance.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::structs::{AdminBlockInstanceView, ModlogListParams};
|
||||||
|
use diesel::{
|
||||||
|
result::Error,
|
||||||
|
BoolExpressionMethods,
|
||||||
|
ExpressionMethods,
|
||||||
|
IntoSql,
|
||||||
|
JoinOnDsl,
|
||||||
|
NullableExpressionMethods,
|
||||||
|
QueryDsl,
|
||||||
|
};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
newtypes::PersonId,
|
||||||
|
schema::{admin_block_instance, instance, person},
|
||||||
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl AdminBlockInstanceView {
|
||||||
|
pub async fn list(pool: &mut DbPool<'_>, params: ModlogListParams) -> Result<Vec<Self>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
|
||||||
|
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
|
||||||
|
let show_mod_names = !params.hide_modlog_names;
|
||||||
|
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
|
||||||
|
|
||||||
|
let admin_names_join = admin_block_instance::admin_person_id
|
||||||
|
.eq(person::id)
|
||||||
|
.and(show_mod_names_expr.or(person::id.eq(admin_person_id_join)));
|
||||||
|
let mut query = admin_block_instance::table
|
||||||
|
.left_join(person::table.on(admin_names_join))
|
||||||
|
.inner_join(instance::table)
|
||||||
|
.select((
|
||||||
|
admin_block_instance::all_columns,
|
||||||
|
instance::all_columns,
|
||||||
|
person::all_columns.nullable(),
|
||||||
|
))
|
||||||
|
.into_boxed();
|
||||||
|
|
||||||
|
if let Some(admin_person_id) = params.mod_person_id {
|
||||||
|
query = query.filter(admin_block_instance::admin_person_id.eq(admin_person_id));
|
||||||
|
};
|
||||||
|
|
||||||
|
let (limit, offset) = limit_and_offset(params.page, params.limit)?;
|
||||||
|
|
||||||
|
query
|
||||||
|
.limit(limit)
|
||||||
|
.offset(offset)
|
||||||
|
.order_by(admin_block_instance::when_.desc())
|
||||||
|
.load::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,8 @@
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
|
pub mod admin_allow_instance;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
pub mod admin_block_instance;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
pub mod admin_purge_comment_view;
|
pub mod admin_purge_comment_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod admin_purge_community_view;
|
pub mod admin_purge_community_view;
|
||||||
|
|
|
@ -5,22 +5,29 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
community::Community,
|
community::Community,
|
||||||
moderator::{
|
instance::Instance,
|
||||||
AdminPurgeComment,
|
mod_log::{
|
||||||
AdminPurgeCommunity,
|
admin::{
|
||||||
AdminPurgePerson,
|
AdminAllowInstance,
|
||||||
AdminPurgePost,
|
AdminBlockInstance,
|
||||||
ModAdd,
|
AdminPurgeComment,
|
||||||
ModAddCommunity,
|
AdminPurgeCommunity,
|
||||||
ModBan,
|
AdminPurgePerson,
|
||||||
ModBanFromCommunity,
|
AdminPurgePost,
|
||||||
ModFeaturePost,
|
},
|
||||||
ModHideCommunity,
|
moderator::{
|
||||||
ModLockPost,
|
ModAdd,
|
||||||
ModRemoveComment,
|
ModAddCommunity,
|
||||||
ModRemoveCommunity,
|
ModBan,
|
||||||
ModRemovePost,
|
ModBanFromCommunity,
|
||||||
ModTransferCommunity,
|
ModFeaturePost,
|
||||||
|
ModHideCommunity,
|
||||||
|
ModLockPost,
|
||||||
|
ModRemoveComment,
|
||||||
|
ModRemoveCommunity,
|
||||||
|
ModRemovePost,
|
||||||
|
ModTransferCommunity,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
person::Person,
|
person::Person,
|
||||||
post::Post,
|
post::Post,
|
||||||
|
@ -233,6 +240,32 @@ pub struct AdminPurgePostView {
|
||||||
pub community: Community,
|
pub community: Community,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a post.
|
||||||
|
pub struct AdminBlockInstanceView {
|
||||||
|
pub admin_block_instance: AdminBlockInstance,
|
||||||
|
pub instance: Instance,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub admin: Option<Person>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a post.
|
||||||
|
pub struct AdminAllowInstanceView {
|
||||||
|
pub admin_block_instance: AdminAllowInstance,
|
||||||
|
pub instance: Instance,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub admin: Option<Person>,
|
||||||
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
|
|
@ -199,10 +199,14 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
federation_allowlist::FederationAllowList,
|
source::{
|
||||||
federation_blocklist::FederationBlockList,
|
federation_allowlist::{FederationAllowList, FederationAllowListForm},
|
||||||
instance::InstanceForm,
|
federation_blocklist::{FederationBlockList, FederationBlockListForm},
|
||||||
|
instance::InstanceForm,
|
||||||
|
person::{Person, PersonInsertForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
@ -318,14 +322,22 @@ mod test {
|
||||||
async fn test_send_manager_blocked() -> LemmyResult<()> {
|
async fn test_send_manager_blocked() -> LemmyResult<()> {
|
||||||
let mut data = TestData::init(1, 1).await?;
|
let mut data = TestData::init(1, 1).await?;
|
||||||
|
|
||||||
let domain = data.instances[0].domain.clone();
|
let instance_id = data.instances[0].id;
|
||||||
FederationBlockList::replace(&mut data.context.pool(), Some(vec![domain])).await?;
|
let form = PersonInsertForm::new("tim".to_string(), String::new(), instance_id);
|
||||||
|
let person = Person::create(&mut data.context.pool(), &form).await?;
|
||||||
|
let form = FederationBlockListForm {
|
||||||
|
instance_id,
|
||||||
|
updated: None,
|
||||||
|
expires: None,
|
||||||
|
};
|
||||||
|
FederationBlockList::block(&mut data.context.pool(), &form).await?;
|
||||||
data.run().await?;
|
data.run().await?;
|
||||||
let workers = &data.send_manager.workers;
|
let workers = &data.send_manager.workers;
|
||||||
assert_eq!(2, workers.len());
|
assert_eq!(2, workers.len());
|
||||||
assert!(workers.contains_key(&data.instances[1].id));
|
assert!(workers.contains_key(&data.instances[1].id));
|
||||||
assert!(workers.contains_key(&data.instances[2].id));
|
assert!(workers.contains_key(&data.instances[2].id));
|
||||||
|
|
||||||
|
Person::delete(&mut data.context.pool(), person.id).await?;
|
||||||
data.cleanup().await?;
|
data.cleanup().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -336,13 +348,20 @@ mod test {
|
||||||
async fn test_send_manager_allowed() -> LemmyResult<()> {
|
async fn test_send_manager_allowed() -> LemmyResult<()> {
|
||||||
let mut data = TestData::init(1, 1).await?;
|
let mut data = TestData::init(1, 1).await?;
|
||||||
|
|
||||||
let domain = data.instances[0].domain.clone();
|
let instance_id = data.instances[0].id;
|
||||||
FederationAllowList::replace(&mut data.context.pool(), Some(vec![domain])).await?;
|
let form = PersonInsertForm::new("tim".to_string(), String::new(), instance_id);
|
||||||
|
let person = Person::create(&mut data.context.pool(), &form).await?;
|
||||||
|
let form = FederationAllowListForm {
|
||||||
|
instance_id: data.instances[0].id,
|
||||||
|
updated: None,
|
||||||
|
};
|
||||||
|
FederationAllowList::allow(&mut data.context.pool(), &form).await?;
|
||||||
data.run().await?;
|
data.run().await?;
|
||||||
let workers = &data.send_manager.workers;
|
let workers = &data.send_manager.workers;
|
||||||
assert_eq!(1, workers.len());
|
assert_eq!(1, workers.len());
|
||||||
assert!(workers.contains_key(&data.instances[0].id));
|
assert!(workers.contains_key(&data.instances[0].id));
|
||||||
|
|
||||||
|
Person::delete(&mut data.context.pool(), person.id).await?;
|
||||||
data.cleanup().await?;
|
data.cleanup().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
body::BodyStream,
|
body::{BodyStream, BoxBody},
|
||||||
http::{
|
http::{
|
||||||
header::{HeaderName, ACCEPT_ENCODING, HOST},
|
header::{HeaderName, ACCEPT_ENCODING, HOST},
|
||||||
Method,
|
Method,
|
||||||
StatusCode,
|
StatusCode,
|
||||||
},
|
},
|
||||||
web::{self, Query},
|
web::*,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
HttpResponse,
|
HttpResponse,
|
||||||
|
Responder,
|
||||||
};
|
};
|
||||||
use futures::stream::{Stream, StreamExt};
|
use futures::stream::{Stream, StreamExt};
|
||||||
use http::HeaderValue;
|
use http::HeaderValue;
|
||||||
|
@ -24,22 +25,18 @@ use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub fn config(
|
pub fn config(cfg: &mut ServiceConfig, client: ClientWithMiddleware, rate_limit: &RateLimitCell) {
|
||||||
cfg: &mut web::ServiceConfig,
|
|
||||||
client: ClientWithMiddleware,
|
|
||||||
rate_limit: &RateLimitCell,
|
|
||||||
) {
|
|
||||||
cfg
|
cfg
|
||||||
.app_data(web::Data::new(client))
|
.app_data(Data::new(client))
|
||||||
.service(
|
.service(
|
||||||
web::resource("/pictrs/image")
|
resource("/pictrs/image")
|
||||||
.wrap(rate_limit.image())
|
.wrap(rate_limit.image())
|
||||||
.route(web::post().to(upload)),
|
.route(post().to(upload)),
|
||||||
)
|
)
|
||||||
// This has optional query params: /image/{filename}?format=jpg&thumbnail=256
|
// This has optional query params: /image/{filename}?format=jpg&thumbnail=256
|
||||||
.service(web::resource("/pictrs/image/{filename}").route(web::get().to(full_res)))
|
.service(resource("/pictrs/image/{filename}").route(get().to(full_res)))
|
||||||
.service(web::resource("/pictrs/image/delete/{token}/{filename}").route(web::get().to(delete)))
|
.service(resource("/pictrs/image/delete/{token}/{filename}").route(get().to(delete)))
|
||||||
.service(web::resource("/pictrs/healthz").route(web::get().to(healthz)));
|
.service(resource("/pictrs/healthz").route(get().to(healthz)));
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ProcessUrl {
|
trait ProcessUrl {
|
||||||
|
@ -129,11 +126,11 @@ fn adapt_request(
|
||||||
|
|
||||||
async fn upload(
|
async fn upload(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
body: web::Payload,
|
body: Payload,
|
||||||
// require login
|
// require login
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
client: web::Data<ClientWithMiddleware>,
|
client: Data<ClientWithMiddleware>,
|
||||||
context: web::Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
) -> LemmyResult<HttpResponse> {
|
) -> LemmyResult<HttpResponse> {
|
||||||
// TODO: check rate limit here
|
// TODO: check rate limit here
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs_config()?;
|
||||||
|
@ -173,11 +170,11 @@ async fn upload(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn full_res(
|
async fn full_res(
|
||||||
filename: web::Path<String>,
|
filename: Path<String>,
|
||||||
web::Query(params): web::Query<PictrsGetParams>,
|
Query(params): Query<PictrsGetParams>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
client: web::Data<ClientWithMiddleware>,
|
client: Data<ClientWithMiddleware>,
|
||||||
context: web::Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
local_user_view: Option<LocalUserView>,
|
local_user_view: Option<LocalUserView>,
|
||||||
) -> LemmyResult<HttpResponse> {
|
) -> LemmyResult<HttpResponse> {
|
||||||
// block access to images if instance is private and unauthorized, public
|
// block access to images if instance is private and unauthorized, public
|
||||||
|
@ -226,10 +223,10 @@ async fn image(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete(
|
async fn delete(
|
||||||
components: web::Path<(String, String)>,
|
components: Path<(String, String)>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
client: web::Data<ClientWithMiddleware>,
|
client: Data<ClientWithMiddleware>,
|
||||||
context: web::Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
// require login
|
// require login
|
||||||
_local_user_view: LocalUserView,
|
_local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<HttpResponse> {
|
) -> LemmyResult<HttpResponse> {
|
||||||
|
@ -253,8 +250,8 @@ async fn delete(
|
||||||
|
|
||||||
async fn healthz(
|
async fn healthz(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
client: web::Data<ClientWithMiddleware>,
|
client: Data<ClientWithMiddleware>,
|
||||||
context: web::Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
) -> LemmyResult<HttpResponse> {
|
) -> LemmyResult<HttpResponse> {
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs_config()?;
|
||||||
let url = format!("{}healthz", pictrs_config.url);
|
let url = format!("{}healthz", pictrs_config.url);
|
||||||
|
@ -273,9 +270,9 @@ async fn healthz(
|
||||||
pub async fn image_proxy(
|
pub async fn image_proxy(
|
||||||
Query(params): Query<ImageProxyParams>,
|
Query(params): Query<ImageProxyParams>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
client: web::Data<ClientWithMiddleware>,
|
client: Data<ClientWithMiddleware>,
|
||||||
context: web::Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
) -> LemmyResult<HttpResponse> {
|
) -> LemmyResult<Either<HttpResponse<()>, HttpResponse<BoxBody>>> {
|
||||||
let url = Url::parse(¶ms.url)?;
|
let url = Url::parse(¶ms.url)?;
|
||||||
|
|
||||||
// Check that url corresponds to a federated image so that this can't be abused as a proxy
|
// Check that url corresponds to a federated image so that this can't be abused as a proxy
|
||||||
|
@ -283,10 +280,19 @@ pub async fn image_proxy(
|
||||||
RemoteImage::validate(&mut context.pool(), url.clone().into()).await?;
|
RemoteImage::validate(&mut context.pool(), url.clone().into()).await?;
|
||||||
|
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs_config()?;
|
||||||
|
|
||||||
let processed_url = params.process_url(¶ms.url, &pictrs_config.url);
|
let processed_url = params.process_url(¶ms.url, &pictrs_config.url);
|
||||||
|
|
||||||
image(processed_url, req, &client).await
|
let bypass_proxy = pictrs_config
|
||||||
|
.proxy_bypass_domains
|
||||||
|
.iter()
|
||||||
|
.any(|s| url.domain().is_some_and(|d| d == s));
|
||||||
|
if bypass_proxy {
|
||||||
|
// Bypass proxy and redirect user to original image
|
||||||
|
Ok(Either::Left(Redirect::to(url.to_string()).respond_to(&req)))
|
||||||
|
} else {
|
||||||
|
// Proxy the image data through Lemmy
|
||||||
|
Ok(Either::Right(image(processed_url, req, &client).await?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_send<S>(mut stream: S) -> impl Stream<Item = S::Item> + Send + Unpin + 'static
|
fn make_send<S>(mut stream: S) -> impl Stream<Item = S::Item> + Send + Unpin + 'static
|
||||||
|
|
|
@ -151,6 +151,7 @@ pub enum LemmyErrorType {
|
||||||
CommunityHasNoFollowers,
|
CommunityHasNoFollowers,
|
||||||
PostScheduleTimeMustBeInFuture,
|
PostScheduleTimeMustBeInFuture,
|
||||||
TooManyScheduledPosts,
|
TooManyScheduledPosts,
|
||||||
|
CannotCombineFederationBlocklistAndAllowlist,
|
||||||
FederationError {
|
FederationError {
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
error: Option<FederationError>,
|
error: Option<FederationError>,
|
||||||
|
|
|
@ -88,6 +88,15 @@ pub struct PictrsConfig {
|
||||||
#[default(PictrsImageMode::StoreLinkPreviews)]
|
#[default(PictrsImageMode::StoreLinkPreviews)]
|
||||||
pub(super) image_mode: PictrsImageMode,
|
pub(super) image_mode: PictrsImageMode,
|
||||||
|
|
||||||
|
/// Allows bypassing proxy for specific image hosts when using ProxyAllImages.
|
||||||
|
///
|
||||||
|
/// imgur.com is bypassed by default to avoid rate limit errors. When specifying any bypass
|
||||||
|
/// in the config, this default is ignored and you need to list imgur explicitly. To proxy imgur
|
||||||
|
/// requests, specify a noop bypass list, eg `proxy_bypass_domains ["example.org"]`.
|
||||||
|
#[default(vec!["i.imgur.com".to_string()])]
|
||||||
|
#[doku(example = "i.imgur.com")]
|
||||||
|
pub proxy_bypass_domains: Vec<String>,
|
||||||
|
|
||||||
/// Timeout for uploading images to pictrs (in seconds)
|
/// Timeout for uploading images to pictrs (in seconds)
|
||||||
#[default(30)]
|
#[default(30)]
|
||||||
pub upload_timeout: u64,
|
pub upload_timeout: u64,
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
ALTER TABLE federation_blocklist
|
||||||
|
DROP expires;
|
||||||
|
|
||||||
|
DROP TABLE admin_block_instance;
|
||||||
|
|
||||||
|
DROP TABLE admin_allow_instance;
|
||||||
|
|
22
migrations/2024-11-28-142005_instance-block-mod-log/up.sql
Normal file
22
migrations/2024-11-28-142005_instance-block-mod-log/up.sql
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
ALTER TABLE federation_blocklist
|
||||||
|
ADD COLUMN expires timestamptz;
|
||||||
|
|
||||||
|
CREATE TABLE admin_block_instance (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
instance_id int NOT NULL REFERENCES instance (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
admin_person_id int NOT NULL REFERENCES person (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
blocked bool NOT NULL,
|
||||||
|
reason text,
|
||||||
|
expires timestamptz,
|
||||||
|
when_ timestamptz NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE admin_allow_instance (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
instance_id int NOT NULL REFERENCES instance (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
admin_person_id int NOT NULL REFERENCES person (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
allowed bool NOT NULL,
|
||||||
|
reason text,
|
||||||
|
when_ timestamptz NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
|
@ -69,7 +69,6 @@ use lemmy_api::{
|
||||||
resolve::resolve_pm_report,
|
resolve::resolve_pm_report,
|
||||||
},
|
},
|
||||||
site::{
|
site::{
|
||||||
block::block_instance,
|
|
||||||
federated_instances::get_federated_instances,
|
federated_instances::get_federated_instances,
|
||||||
leave_admin::leave_admin,
|
leave_admin::leave_admin,
|
||||||
list_all_media::list_all_media,
|
list_all_media::list_all_media,
|
||||||
|
@ -86,6 +85,7 @@ use lemmy_api::{
|
||||||
list::list_registration_applications,
|
list::list_registration_applications,
|
||||||
unread_count::get_unread_registration_application_count,
|
unread_count::get_unread_registration_application_count,
|
||||||
},
|
},
|
||||||
|
user_block_instance::user_block_instance,
|
||||||
},
|
},
|
||||||
sitemap::get_sitemap,
|
sitemap::get_sitemap,
|
||||||
};
|
};
|
||||||
|
@ -149,7 +149,7 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
// Admin Actions
|
// Admin Actions
|
||||||
.route("", post().to(create_site))
|
.route("", post().to(create_site))
|
||||||
.route("", put().to(update_site))
|
.route("", put().to(update_site))
|
||||||
.route("/block", post().to(block_instance)),
|
.route("/block", post().to(user_block_instance)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
resource("/modlog")
|
resource("/modlog")
|
||||||
|
|
|
@ -76,7 +76,8 @@ use lemmy_api::{
|
||||||
resolve::resolve_pm_report,
|
resolve::resolve_pm_report,
|
||||||
},
|
},
|
||||||
site::{
|
site::{
|
||||||
block::block_instance,
|
admin_allow_instance::admin_allow_instance,
|
||||||
|
admin_block_instance::admin_block_instance,
|
||||||
federated_instances::get_federated_instances,
|
federated_instances::get_federated_instances,
|
||||||
leave_admin::leave_admin,
|
leave_admin::leave_admin,
|
||||||
list_all_media::list_all_media,
|
list_all_media::list_all_media,
|
||||||
|
@ -171,8 +172,7 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
.route("", get().to(get_site_v4))
|
.route("", get().to(get_site_v4))
|
||||||
// Admin Actions
|
// Admin Actions
|
||||||
.route("", post().to(create_site))
|
.route("", post().to(create_site))
|
||||||
.route("", put().to(update_site))
|
.route("", put().to(update_site)),
|
||||||
.route("/block", post().to(block_instance)),
|
|
||||||
)
|
)
|
||||||
.route("/modlog", get().to(get_mod_log))
|
.route("/modlog", get().to(get_mod_log))
|
||||||
.service(
|
.service(
|
||||||
|
@ -358,7 +358,9 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
)
|
)
|
||||||
.route("/ban", post().to(ban_from_site))
|
.route("/ban", post().to(ban_from_site))
|
||||||
.route("/banned", get().to(list_banned_users))
|
.route("/banned", get().to(list_banned_users))
|
||||||
.route("/leave", post().to(leave_admin)),
|
.route("/leave", post().to(leave_admin))
|
||||||
|
.route("block_instance", post().to(admin_block_instance))
|
||||||
|
.route("allow_instance", post().to(admin_allow_instance)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
scope("/custom_emoji")
|
scope("/custom_emoji")
|
||||||
|
|
|
@ -23,6 +23,7 @@ use lemmy_db_schema::{
|
||||||
comment,
|
comment,
|
||||||
community,
|
community,
|
||||||
community_actions,
|
community_actions,
|
||||||
|
federation_blocklist,
|
||||||
instance,
|
instance,
|
||||||
person,
|
person,
|
||||||
post,
|
post,
|
||||||
|
@ -58,6 +59,7 @@ pub async fn setup(context: Data<LemmyContext>) -> LemmyResult<()> {
|
||||||
async move {
|
async move {
|
||||||
active_counts(&mut context.pool()).await;
|
active_counts(&mut context.pool()).await;
|
||||||
update_banned_when_expired(&mut context.pool()).await;
|
update_banned_when_expired(&mut context.pool()).await;
|
||||||
|
delete_instance_block_when_expired(&mut context.pool()).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -113,6 +115,7 @@ async fn startup_jobs(pool: &mut DbPool<'_>) {
|
||||||
active_counts(pool).await;
|
active_counts(pool).await;
|
||||||
update_hot_ranks(pool).await;
|
update_hot_ranks(pool).await;
|
||||||
update_banned_when_expired(pool).await;
|
update_banned_when_expired(pool).await;
|
||||||
|
delete_instance_block_when_expired(pool).await;
|
||||||
clear_old_activities(pool).await;
|
clear_old_activities(pool).await;
|
||||||
overwrite_deleted_posts_and_comments(pool).await;
|
overwrite_deleted_posts_and_comments(pool).await;
|
||||||
delete_old_denied_users(pool).await;
|
delete_old_denied_users(pool).await;
|
||||||
|
@ -446,6 +449,27 @@ async fn update_banned_when_expired(pool: &mut DbPool<'_>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set banned to false after ban expires
|
||||||
|
async fn delete_instance_block_when_expired(pool: &mut DbPool<'_>) {
|
||||||
|
info!("Delete instance blocks when expired ...");
|
||||||
|
let conn = get_conn(pool).await;
|
||||||
|
|
||||||
|
match conn {
|
||||||
|
Ok(mut conn) => {
|
||||||
|
diesel::delete(
|
||||||
|
federation_blocklist::table.filter(federation_blocklist::expires.lt(now().nullable())),
|
||||||
|
)
|
||||||
|
.execute(&mut conn)
|
||||||
|
.await
|
||||||
|
.inspect_err(|e| error!("Failed to remove federation_blocklist expired rows: {e}"))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to get connection from pool: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Find all unpublished posts with scheduled date in the future, and publish them.
|
/// Find all unpublished posts with scheduled date in the future, and publish them.
|
||||||
async fn publish_scheduled_posts(context: &Data<LemmyContext>) {
|
async fn publish_scheduled_posts(context: &Data<LemmyContext>) {
|
||||||
let pool = &mut context.pool();
|
let pool = &mut context.pool();
|
||||||
|
|
Loading…
Reference in a new issue