]> Untitled Git - lemmy.git/blob - ui/src/components/login.tsx
Spam
[lemmy.git] / ui / src / components / login.tsx
1 import { Component, linkEvent } from 'inferno';
2 import { Subscription } from "rxjs";
3 import { retryWhen, delay, take } from 'rxjs/operators';
4 import { LoginForm, RegisterForm, LoginResponse, UserOperation } from '../interfaces';
5 import { WebSocketService, UserService } from '../services';
6 import { msgOp } from '../utils';
7
8 interface State {
9   loginForm: LoginForm;
10   registerForm: RegisterForm;
11   loginLoading: boolean;
12   registerLoading: boolean;
13   spamNada: string;
14 }
15
16
17 export class Login extends Component<any, State> {
18   private subscription: Subscription;
19
20   emptyState: State = {
21     loginForm: {
22       username_or_email: undefined,
23       password: undefined
24     },
25     registerForm: {
26       username: undefined,
27       password: undefined,
28       password_verify: undefined,
29       admin: false,
30       spam_timer: undefined,
31     },
32     loginLoading: false,
33     registerLoading: false,
34     spamNada: undefined
35   }
36
37   constructor(props: any, context: any) {
38     super(props, context);
39
40     this.state = this.emptyState;
41
42     this.subscription = WebSocketService.Instance.subject
43     .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
44     .subscribe(
45       (msg) => this.parseMessage(msg),
46         (err) => console.error(err),
47         () => console.log("complete")
48     );
49   }
50
51   componentWillUnmount() {
52     this.subscription.unsubscribe();
53   }
54
55   componentDidMount() {
56     document.title = "Login - Lemmy";
57   }
58
59   render() {
60     return (
61       <div class="container">
62         <div class="row">
63           <div class="col-12 col-lg-6 mb-4">
64             {this.loginForm()}
65           </div>
66           <div class="col-12 col-lg-6">
67             {this.registerForm()}
68           </div>
69         </div>
70       </div>
71     )
72   }
73
74   loginForm() {
75     return (
76       <div>
77         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
78           <h5>Login</h5>
79           <div class="form-group row">
80             <label class="col-sm-2 col-form-label">Email or Username</label>
81             <div class="col-sm-10">
82               <input type="text" class="form-control" value={this.state.loginForm.username_or_email} onInput={linkEvent(this, this.handleLoginUsernameChange)} required minLength={3} />
83             </div>
84           </div>
85           <div class="form-group row">
86             <label class="col-sm-2 col-form-label">Password</label>
87             <div class="col-sm-10">
88               <input type="password" value={this.state.loginForm.password} onInput={linkEvent(this, this.handleLoginPasswordChange)} class="form-control" required />
89             </div>
90           </div>
91           <div class="form-group row">
92             <div class="col-sm-10">
93               <button type="submit" class="btn btn-secondary">{this.state.loginLoading ? 
94               <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Login'}</button>
95             </div>
96           </div>
97         </form>
98         Forgot your password or deleted your account? Reset your password. TODO
99       </div>
100     );
101   }
102   registerForm() {
103     return (
104       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
105         <h5>Sign Up</h5>
106         <div class="form-group row">
107           <label class="col-sm-2 col-form-label">Username</label>
108           <div class="col-sm-10">
109             <input type="text" class="form-control" value={this.state.registerForm.username} onInput={linkEvent(this, this.handleRegisterUsernameChange)} required minLength={3} maxLength={20} pattern="[a-zA-Z0-9_]+" />
110           </div>
111         </div>
112         <div class="form-group row">
113           <label class="col-sm-2 col-form-label">Email</label>
114           <div class="col-sm-10">
115             <input type="email" class="form-control" placeholder="Optional" value={this.state.registerForm.email} onInput={linkEvent(this, this.handleRegisterEmailChange)} minLength={3} />
116           </div>
117         </div>
118         <div class="form-group row">
119           <label class="col-sm-2 col-form-label">Password</label>
120           <div class="col-sm-10">
121             <input type="password" value={this.state.registerForm.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required />
122           </div>
123         </div>
124         <div class="form-group row">
125           <label class="col-sm-2 col-form-label">Verify Password</label>
126           <div class="col-sm-10">
127             <input type="password" value={this.state.registerForm.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required />
128           </div>
129         </div>
130         <input type="hidden" value={this.state.registerForm.spam_timer} />
131         <input type="text" class="d-none" value={this.state.spamNada} onInput={linkEvent(this, this.handleSpamNada)} />
132         <div class="form-group row">
133           <div class="col-sm-10">
134             <button type="submit" class="btn btn-secondary">{this.state.registerLoading ? 
135             <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Sign Up'}</button>
136
137           </div>
138         </div>
139       </form>
140     );
141   }
142
143   handleLoginSubmit(i: Login, event: any) {
144     event.preventDefault();
145     i.state.loginLoading = true;
146     i.setState(i.state);
147     WebSocketService.Instance.login(i.state.loginForm);
148   }
149
150   handleLoginUsernameChange(i: Login, event: any) {
151     i.state.loginForm.username_or_email = event.target.value;
152     i.setState(i.state);
153   }
154
155   handleLoginPasswordChange(i: Login, event: any) {
156     i.state.loginForm.password = event.target.value;
157     i.setState(i.state);
158   }
159
160   handleRegisterSubmit(i: Login, event: any) {
161     event.preventDefault();
162     i.state.registerLoading = true;
163     i.setState(i.state);
164     event.preventDefault();
165
166     let endTimer = new Date().getTime();
167     let elapsed = endTimer - i.state.registerForm.spam_timer;
168
169     i.state.registerForm.spam_timer = elapsed;
170     if (elapsed > 1142 && i.state.spamNada == undefined) {
171       WebSocketService.Instance.register(i.state.registerForm);
172     } else {
173       window.location.href = "https://github.com/dessalines/lemmy";
174     }
175   }
176
177   handleRegisterUsernameChange(i: Login, event: any) {
178     i.state.registerForm.username = event.target.value;
179     i.state.registerForm.spam_timer = new Date().getTime();
180     i.setState(i.state);
181   }
182
183   handleSpamNada(i: Login, event: any) {
184     i.state.spamNada = event.target.value;
185     i.setState(i.state);
186   }
187
188   handleRegisterEmailChange(i: Login, event: any) {
189     i.state.registerForm.email = event.target.value;
190     i.setState(i.state);
191   }
192
193   handleRegisterPasswordChange(i: Login, event: any) {
194     i.state.registerForm.password = event.target.value;
195     i.setState(i.state);
196   }
197
198   handleRegisterPasswordVerifyChange(i: Login, event: any) {
199     i.state.registerForm.password_verify = event.target.value;
200     i.setState(i.state);
201   }
202
203   parseMessage(msg: any) {
204     let op: UserOperation = msgOp(msg);
205     if (msg.error) {
206       alert(msg.error);
207       this.state = this.emptyState;
208       this.setState(this.state);
209       return;
210     } else {
211       if (op == UserOperation.Login) {
212         this.state.loginLoading = false;
213         this.state.registerLoading = false;
214         let res: LoginResponse = msg;
215         UserService.Instance.login(res);
216         this.props.history.push('/');
217       } else if (op == UserOperation.Register) {
218         this.state.loginLoading = false;
219         this.state.registerLoading = false;
220         let res: LoginResponse = msg;
221         UserService.Instance.login(res);
222         this.props.history.push('/communities');
223       }
224     }
225   }
226
227 }