From b96e16b4e9a8baeddc3c97f449ef6c1cad1fbe29 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 30 Dec 2021 10:26:45 -0500 Subject: [PATCH] Private instances (#523) * Updating translations. * Adding registration applications. * Updating translations. * Adding verify email route. * Fix missing signup question bug. * Updating translations. * A few fixes from comments on lemmy PR. * v0.15.0-rc.4 * Some suggestions from PR. * v0.15.0-rc.5 * Adding optional auth to modlog fetches. * v0.15.0-rc.6 * Hide deny / approve buttons --- lemmy-translations | 2 +- package.json | 4 +- src/server/index.tsx | 6 +- src/shared/components/app/navbar.tsx | 86 +++++- ...{comment_report.tsx => comment-report.tsx} | 11 +- .../components/common/markdown-textarea.tsx | 2 +- .../common/registration-application.tsx | 150 +++++++++++ src/shared/components/common/symbols.tsx | 3 + src/shared/components/home/home.tsx | 1 + src/shared/components/home/login.tsx | 2 - src/shared/components/home/signup.tsx | 100 +++++-- src/shared/components/home/site-form.tsx | 138 ++++++++-- src/shared/components/modlog.tsx | 5 + .../password-change.tsx} | 0 .../person/registration-applications.tsx | 249 ++++++++++++++++++ src/shared/components/person/reports.tsx | 4 +- src/shared/components/person/settings.tsx | 5 + src/shared/components/person/verify-email.tsx | 97 +++++++ .../post/{post_report.tsx => post-report.tsx} | 11 +- src/shared/routes.ts | 13 +- src/shared/services/UserService.ts | 2 + src/shared/utils.ts | 15 ++ yarn.lock | 8 +- 23 files changed, 849 insertions(+), 65 deletions(-) rename src/shared/components/comment/{comment_report.tsx => comment-report.tsx} (92%) create mode 100644 src/shared/components/common/registration-application.tsx rename src/shared/components/{home/password_change.tsx => person/password-change.tsx} (100%) create mode 100644 src/shared/components/person/registration-applications.tsx create mode 100644 src/shared/components/person/verify-email.tsx rename src/shared/components/post/{post_report.tsx => post-report.tsx} (92%) diff --git a/lemmy-translations b/lemmy-translations index 0412b6b3..1e0bb992 160000 --- a/lemmy-translations +++ b/lemmy-translations @@ -1 +1 @@ -Subproject commit 0412b6b349e5e8d6ac3ed88801187833e95c72c9 +Subproject commit 1e0bb9920cda13bb128c87e85125b98ab8f319b6 diff --git a/package.json b/package.json index 7621abb5..ba0665ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "lemmy-ui", "description": "An isomorphic UI for lemmy", - "version": "0.14.5", + "version": "0.15.0-rc.6", "author": "Dessalines ", "license": "AGPL-3.0", "scripts": { @@ -72,7 +72,7 @@ "husky": "^7.0.4", "import-sort-style-module": "^6.0.0", "iso-639-1": "^2.1.10", - "lemmy-js-client": "0.14.0-rc.1", + "lemmy-js-client": "0.15.0-rc.6", "lint-staged": "^12.1.2", "mini-css-extract-plugin": "^2.4.5", "node-fetch": "^2.6.1", diff --git a/src/server/index.tsx b/src/server/index.tsx index 5bf79f17..82d0379b 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -91,7 +91,11 @@ server.get("/*", async (req, res) => { if (routeData[0] && routeData[0].error) { let errCode = routeData[0].error; console.error(errCode); - return res.redirect(`/404?err=${errCode}`); + if (errCode == "instance_is_private") { + return res.redirect(`/signup`); + } else { + return res.redirect(`/404?err=${errCode}`); + } } let isoData: IsoData = { diff --git a/src/shared/components/app/navbar.tsx b/src/shared/components/app/navbar.tsx index 2a40915d..57555410 100644 --- a/src/shared/components/app/navbar.tsx +++ b/src/shared/components/app/navbar.tsx @@ -7,6 +7,8 @@ import { GetSiteResponse, GetUnreadCount, GetUnreadCountResponse, + GetUnreadRegistrationApplicationCount, + GetUnreadRegistrationApplicationCountResponse, PrivateMessageResponse, UserOperation, } from "lemmy-js-client"; @@ -41,6 +43,7 @@ interface NavbarState { expanded: boolean; unreadInboxCount: number; unreadReportCount: number; + unreadApplicationCount: number; searchParam: string; toggleSearch: boolean; showDropdown: boolean; @@ -52,11 +55,13 @@ export class Navbar extends Component { private userSub: Subscription; private unreadInboxCountSub: Subscription; private unreadReportCountSub: Subscription; + private unreadApplicationCountSub: Subscription; private searchTextField: RefObject; emptyState: NavbarState = { isLoggedIn: !!this.props.site_res.my_user, unreadInboxCount: 0, unreadReportCount: 0, + unreadApplicationCount: 0, expanded: false, searchParam: "", toggleSearch: false, @@ -115,6 +120,11 @@ export class Navbar extends Component { UserService.Instance.unreadReportCountSub.subscribe(res => { this.setState({ unreadReportCount: res }); }); + // Subscribe to unread application count + this.unreadApplicationCountSub = + UserService.Instance.unreadApplicationCountSub.subscribe(res => { + this.setState({ unreadApplicationCount: res }); + }); } } @@ -123,6 +133,7 @@ export class Navbar extends Component { this.userSub.unsubscribe(); this.unreadInboxCountSub.unsubscribe(); this.unreadReportCountSub.unsubscribe(); + this.unreadApplicationCountSub.unsubscribe(); } updateUrl() { @@ -215,6 +226,31 @@ export class Navbar extends Component { )} + {UserService.Instance.myUserInfo?.local_user_view.person + .admin && ( + + )} )} + )} + {(!ra.admin_id || (ra.admin_id && accepted)) && ( + + )} + + ); + } + + handleApprove(i: RegistrationApplication) { + i.setState({ denyExpanded: false }); + let form: ApproveRegistrationApplication = { + id: i.props.application.registration_application.id, + deny_reason: "", + approve: true, + auth: authField(), + }; + WebSocketService.Instance.send( + wsClient.approveRegistrationApplication(form) + ); + } + + handleDeny(i: RegistrationApplication) { + if (i.state.denyExpanded) { + i.setState({ denyExpanded: false }); + let form: ApproveRegistrationApplication = { + id: i.props.application.registration_application.id, + approve: false, + deny_reason: i.state.denyReason, + auth: authField(), + }; + WebSocketService.Instance.send( + wsClient.approveRegistrationApplication(form) + ); + } else { + i.setState({ denyExpanded: true }); + } + } + + handleDenyReasonChange(val: string) { + this.state.denyReason = val; + this.setState(this.state); + } +} diff --git a/src/shared/components/common/symbols.tsx b/src/shared/components/common/symbols.tsx index 2035d3c4..d730c15e 100644 --- a/src/shared/components/common/symbols.tsx +++ b/src/shared/components/common/symbols.tsx @@ -12,6 +12,9 @@ export const SYMBOLS = ( xmlnsXlink="http://www.w3.org/1999/xlink" > + + + diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index f44d4cc0..d1451451 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -239,6 +239,7 @@ export class Home extends Component { sort: SortType.Hot, limit: 6, }; + setOptionalAuth(trendingCommunitiesForm, req.auth); promises.push(req.client.listCommunities(trendingCommunitiesForm)); return promises; diff --git a/src/shared/components/home/login.tsx b/src/shared/components/home/login.tsx index 73d7dbeb..5a61d136 100644 --- a/src/shared/components/home/login.tsx +++ b/src/shared/components/home/login.tsx @@ -185,8 +185,6 @@ export class Login extends Component { if (msg.error) { toast(i18n.t(msg.error), "danger"); this.state = this.emptyState; - // Refetch another captcha - WebSocketService.Instance.send(wsClient.getCaptcha()); this.setState(this.state); return; } else { diff --git a/src/shared/components/home/signup.tsx b/src/shared/components/home/signup.tsx index c3fcd20e..75e78561 100644 --- a/src/shared/components/home/signup.tsx +++ b/src/shared/components/home/signup.tsx @@ -17,6 +17,7 @@ import { authField, isBrowser, joinLemmyUrl, + mdToHtml, setIsoData, toast, validEmail, @@ -27,6 +28,7 @@ import { } from "../../utils"; import { HtmlTags } from "../common/html-tags"; import { Icon, Spinner } from "../common/icon"; +import { MarkdownTextArea } from "../common/markdown-textarea"; const passwordStrengthOptions: Options = [ { @@ -77,6 +79,7 @@ export class Signup extends Component { captcha_uuid: undefined, captcha_answer: undefined, honeypot: undefined, + answer: undefined, }, registerLoading: false, captcha: undefined, @@ -88,6 +91,7 @@ export class Signup extends Component { super(props, context); this.state = this.emptyState; + this.handleAnswerChange = this.handleAnswerChange.bind(this); this.parseMessage = this.parseMessage.bind(this); this.subscription = wsSubscribe(this.parseMessage); @@ -104,7 +108,13 @@ export class Signup extends Component { } get documentTitle(): string { - return `${i18n.t("login")} - ${this.state.site_view.site.name}`; + return `${this.titleName} - ${this.state.site_view.site.name}`; + } + + get titleName(): string { + return `${i18n.t( + this.state.site_view.site.private_instance ? "apply_to_join" : "sign_up" + )}`; } get isLemmyMl(): boolean { @@ -128,7 +138,7 @@ export class Signup extends Component { registerForm() { return (
-
{i18n.t("sign_up")}
+
{this.titleName}
@@ -219,6 +235,40 @@ export class Signup extends Component { + {this.state.site_view.site.require_application && ( + <> +
+
+ +
+
+
+ +
+ +
+ +
+
+ + )} + {this.state.captcha && (
- +
{ />
+ {this.state.siteForm.require_application && ( +
+ +
+ +
+
+ )}
@@ -255,6 +273,66 @@ export class SiteForm extends Component {
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+