]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/login.tsx
Private instances (#523)
[lemmy-ui.git] / src / shared / components / home / login.tsx
1 import { Component, linkEvent } from "inferno";
2 import {
3   GetSiteResponse,
4   Login as LoginForm,
5   LoginResponse,
6   PasswordReset,
7   SiteView,
8   UserOperation,
9 } from "lemmy-js-client";
10 import { Subscription } from "rxjs";
11 import { i18n } from "../../i18next";
12 import { UserService, WebSocketService } from "../../services";
13 import {
14   authField,
15   isBrowser,
16   setIsoData,
17   toast,
18   validEmail,
19   wsClient,
20   wsJsonToRes,
21   wsSubscribe,
22   wsUserOp,
23 } from "../../utils";
24 import { HtmlTags } from "../common/html-tags";
25 import { Spinner } from "../common/icon";
26
27 interface State {
28   loginForm: LoginForm;
29   loginLoading: boolean;
30   site_view: SiteView;
31 }
32
33 export class Login extends Component<any, State> {
34   private isoData = setIsoData(this.context);
35   private subscription: Subscription;
36
37   emptyState: State = {
38     loginForm: {
39       username_or_email: undefined,
40       password: undefined,
41     },
42     loginLoading: false,
43     site_view: this.isoData.site_res.site_view,
44   };
45
46   constructor(props: any, context: any) {
47     super(props, context);
48
49     this.state = this.emptyState;
50
51     this.parseMessage = this.parseMessage.bind(this);
52     this.subscription = wsSubscribe(this.parseMessage);
53
54     if (isBrowser()) {
55       WebSocketService.Instance.send(wsClient.getCaptcha());
56     }
57   }
58
59   componentDidMount() {
60     // Navigate to home if already logged in
61     if (UserService.Instance.myUserInfo) {
62       this.context.router.history.push("/");
63     }
64   }
65
66   componentWillUnmount() {
67     if (isBrowser()) {
68       this.subscription.unsubscribe();
69     }
70   }
71
72   get documentTitle(): string {
73     return `${i18n.t("login")} - ${this.state.site_view.site.name}`;
74   }
75
76   get isLemmyMl(): boolean {
77     return isBrowser() && window.location.hostname == "lemmy.ml";
78   }
79
80   render() {
81     return (
82       <div class="container">
83         <HtmlTags
84           title={this.documentTitle}
85           path={this.context.router.route.match.url}
86         />
87         <div class="row">
88           <div class="col-12 col-lg-6 offset-lg-3">{this.loginForm()}</div>
89         </div>
90       </div>
91     );
92   }
93
94   loginForm() {
95     return (
96       <div>
97         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
98           <h5>{i18n.t("login")}</h5>
99           <div class="form-group row">
100             <label
101               class="col-sm-2 col-form-label"
102               htmlFor="login-email-or-username"
103             >
104               {i18n.t("email_or_username")}
105             </label>
106             <div class="col-sm-10">
107               <input
108                 type="text"
109                 class="form-control"
110                 id="login-email-or-username"
111                 value={this.state.loginForm.username_or_email}
112                 onInput={linkEvent(this, this.handleLoginUsernameChange)}
113                 autoComplete="email"
114                 required
115                 minLength={3}
116               />
117             </div>
118           </div>
119           <div class="form-group row">
120             <label class="col-sm-2 col-form-label" htmlFor="login-password">
121               {i18n.t("password")}
122             </label>
123             <div class="col-sm-10">
124               <input
125                 type="password"
126                 id="login-password"
127                 value={this.state.loginForm.password}
128                 onInput={linkEvent(this, this.handleLoginPasswordChange)}
129                 class="form-control"
130                 autoComplete="current-password"
131                 required
132                 maxLength={60}
133               />
134               <button
135                 type="button"
136                 onClick={linkEvent(this, this.handlePasswordReset)}
137                 className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold pointer-events not-allowed"
138                 disabled={!validEmail(this.state.loginForm.username_or_email)}
139                 title={i18n.t("no_password_reset")}
140               >
141                 {i18n.t("forgot_password")}
142               </button>
143             </div>
144           </div>
145           <div class="form-group row">
146             <div class="col-sm-10">
147               <button type="submit" class="btn btn-secondary">
148                 {this.state.loginLoading ? <Spinner /> : i18n.t("login")}
149               </button>
150             </div>
151           </div>
152         </form>
153       </div>
154     );
155   }
156
157   handleLoginSubmit(i: Login, event: any) {
158     event.preventDefault();
159     i.state.loginLoading = true;
160     i.setState(i.state);
161     WebSocketService.Instance.send(wsClient.login(i.state.loginForm));
162   }
163
164   handleLoginUsernameChange(i: Login, event: any) {
165     i.state.loginForm.username_or_email = event.target.value;
166     i.setState(i.state);
167   }
168
169   handleLoginPasswordChange(i: Login, event: any) {
170     i.state.loginForm.password = event.target.value;
171     i.setState(i.state);
172   }
173
174   handlePasswordReset(i: Login, event: any) {
175     event.preventDefault();
176     let resetForm: PasswordReset = {
177       email: i.state.loginForm.username_or_email,
178     };
179     WebSocketService.Instance.send(wsClient.passwordReset(resetForm));
180   }
181
182   parseMessage(msg: any) {
183     let op = wsUserOp(msg);
184     console.log(msg);
185     if (msg.error) {
186       toast(i18n.t(msg.error), "danger");
187       this.state = this.emptyState;
188       this.setState(this.state);
189       return;
190     } else {
191       if (op == UserOperation.Login) {
192         let data = wsJsonToRes<LoginResponse>(msg).data;
193         this.state = this.emptyState;
194         this.setState(this.state);
195         UserService.Instance.login(data);
196         WebSocketService.Instance.send(
197           wsClient.userJoin({
198             auth: authField(),
199           })
200         );
201         toast(i18n.t("logged_in"));
202         this.props.history.push("/");
203       } else if (op == UserOperation.PasswordReset) {
204         toast(i18n.t("reset_password_mail_sent"));
205       } else if (op == UserOperation.GetSite) {
206         let data = wsJsonToRes<GetSiteResponse>(msg).data;
207         this.state.site_view = data.site_view;
208         this.setState(this.state);
209       }
210     }
211   }
212 }