]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/+login/login.component.ts
Increase max log size for test instances
[github/Chocobozzz/PeerTube.git] / client / src / app / +login / login.component.ts
CommitLineData
2570fd9c 1import { environment } from 'src/environments/environment'
67ed6552 2import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'
13e7c3b0 3import { ActivatedRoute, Router } from '@angular/router'
cb28bb92 4import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core'
f375bb3d 5import { HooksService } from '@app/core/plugins/hooks.service'
7ed1edbb 6import { LOGIN_PASSWORD_VALIDATOR, LOGIN_USERNAME_VALIDATOR } from '@app/shared/form-validators/login-validators'
d12b40fb 7import { USER_OTP_TOKEN_VALIDATOR } from '@app/shared/form-validators/user-validators'
5c5bcea2 8import { FormReactive, FormReactiveService, InputTextComponent } from '@app/shared/shared-forms'
a3664dfd 9import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance'
40360c17 10import { NgbAccordion, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
2570fd9c 11import { getExternalAuthHref } from '@shared/core-utils'
9589907c 12import { RegisteredExternalAuthConfig, ServerConfig, ServerErrorCode } from '@shared/models'
b1794c53
C
13
14@Component({
a840d396 15 selector: 'my-login',
d235f6b0
C
16 templateUrl: './login.component.html',
17 styleUrls: [ './login.component.scss' ]
b1794c53
C
18})
19
ebefc902 20export class LoginComponent extends FormReactive implements OnInit, AfterViewInit {
cb28bb92
C
21 private static SESSION_STORAGE_REDIRECT_URL_KEY = 'login-previous-url'
22
f36da21e 23 @ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef
d12b40fb 24 @ViewChild('otpTokenInput') otpTokenInput: InputTextComponent
ecb4e35f 25
40360c17 26 accordion: NgbAccordion
df98563e 27 error: string = null
ecb4e35f 28 forgotPasswordEmail = ''
bc90883f 29
4a8d113b 30 isAuthenticatedWithExternalAuth = false
bc90883f 31 externalAuthError = false
ebefc902 32 externalLogins: string[] = []
192ea60b 33
40360c17
K
34 instanceInformationPanels = {
35 terms: true,
36 administrators: false,
37 features: false,
38 moderation: false,
39 codeOfConduct: false
40 }
41
d12b40fb
C
42 otpStep = false
43
63347a0f 44 private openedForgotPasswordModal: NgbModalRef
ba430d75 45 private serverConfig: ServerConfig
63347a0f 46
b1d40cff 47 constructor (
5c5bcea2 48 protected formReactiveService: FormReactiveService,
ba430d75 49 private route: ActivatedRoute,
63347a0f 50 private modalService: NgbModal,
b1d40cff
C
51 private authService: AuthService,
52 private userService: UserService,
b1d40cff 53 private redirectService: RedirectService,
f8b2c1b4 54 private notifier: Notifier,
cb28bb92 55 private hooks: HooksService,
13e7c3b0
C
56 private storage: SessionStorageService,
57 private router: Router
9df52d66 58 ) {
df98563e 59 super()
4b2f33f3 60 }
b1794c53 61
2b084d70 62 get signupAllowed () {
ba430d75 63 return this.serverConfig.signup.allowed === true
2b084d70
C
64 }
65
11056966
C
66 get instanceName () {
67 return this.serverConfig.instance.name
68 }
69
40360c17
K
70 onTermsClick (event: Event, instanceInformation: HTMLElement) {
71 event.preventDefault()
72
73 if (this.accordion) {
74 this.accordion.expand('terms')
75 instanceInformation.scrollIntoView({ behavior: 'smooth' })
76 }
77 }
78
3b3b1820 79 isEmailDisabled () {
ba430d75 80 return this.serverConfig.email.enabled === false
3b3b1820
C
81 }
82
df98563e 83 ngOnInit () {
4a8d113b
C
84 const snapshot = this.route.snapshot
85
2345e138
C
86 // Avoid undefined errors when accessing form error properties
87 this.buildForm({
88 username: LOGIN_USERNAME_VALIDATOR,
d12b40fb
C
89 password: LOGIN_PASSWORD_VALIDATOR,
90 'otp-token': {
91 VALIDATORS: [], // Will be set dynamically
92 MESSAGES: USER_OTP_TOKEN_VALIDATOR.MESSAGES
93 }
2345e138
C
94 })
95
4a8d113b
C
96 this.serverConfig = snapshot.data.serverConfig
97
98 if (snapshot.queryParams.externalAuthToken) {
99 this.loadExternalAuthToken(snapshot.queryParams.username, snapshot.queryParams.externalAuthToken)
100 return
101 }
ba430d75 102
bc90883f
C
103 if (snapshot.queryParams.externalAuthError) {
104 this.externalAuthError = true
105 return
106 }
cb28bb92 107
13e7c3b0
C
108 const previousUrl = this.redirectService.getPreviousUrl()
109 if (previousUrl && previousUrl !== '/') {
110 this.storage.setItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY, previousUrl)
111 }
ebefc902
C
112 }
113
114 ngAfterViewInit () {
f375bb3d 115 this.hooks.runAction('action:login.init', 'login')
ebefc902
C
116 }
117
118 getExternalLogins () {
119 return this.serverConfig.plugin.registeredExternalAuths
120 }
9fe44067 121
ebefc902 122 getAuthHref (auth: RegisteredExternalAuthConfig) {
2570fd9c 123 return getExternalAuthHref(environment.apiUrl, auth)
0f6da32b
C
124 }
125
df98563e
C
126 login () {
127 this.error = null
4b2f33f3 128
d12b40fb
C
129 const options = {
130 username: this.form.value['username'],
131 password: this.form.value['password'],
132 otpToken: this.form.value['otp-token']
133 }
4b2f33f3 134
d12b40fb
C
135 this.authService.login(options)
136 .pipe()
1378c0d3
C
137 .subscribe({
138 next: () => this.redirectService.redirectToPreviousRoute(),
192ea60b 139
d12b40fb
C
140 error: err => {
141 this.handleError(err)
142 }
1378c0d3 143 })
b1794c53 144 }
ecb4e35f
C
145
146 askResetPassword () {
147 this.userService.askResetPassword(this.forgotPasswordEmail)
1378c0d3
C
148 .subscribe({
149 next: () => {
66357162
C
150 const message = $localize`An email with the reset password instructions will be sent to ${this.forgotPasswordEmail}.
151The link will expire within 1 hour.`
152
f8b2c1b4 153 this.notifier.success(message)
ecb4e35f
C
154 this.hideForgotPasswordModal()
155 },
156
1378c0d3
C
157 error: err => this.notifier.error(err.message)
158 })
ecb4e35f
C
159 }
160
ecb4e35f 161 openForgotPasswordModal () {
63347a0f 162 this.openedForgotPasswordModal = this.modalService.open(this.forgotPasswordModal)
ecb4e35f
C
163 }
164
165 hideForgotPasswordModal () {
63347a0f 166 this.openedForgotPasswordModal.close()
ecb4e35f 167 }
4a8d113b 168
40360c17
K
169 onInstanceAboutAccordionInit (instanceAboutAccordion: InstanceAboutAccordionComponent) {
170 this.accordion = instanceAboutAccordion.accordion
171 }
172
7f28f2dd
C
173 hasUsernameUppercase () {
174 return this.form.value['username'].match(/[A-Z]/)
175 }
176
4a8d113b
C
177 private loadExternalAuthToken (username: string, token: string) {
178 this.isAuthenticatedWithExternalAuth = true
179
d12b40fb 180 this.authService.login({ username, password: null, token })
1378c0d3 181 .subscribe({
cb28bb92 182 next: () => {
13e7c3b0
C
183 const redirectUrl = this.storage.getItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY)
184 if (redirectUrl) {
185 this.storage.removeItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY)
186 return this.router.navigateByUrl(redirectUrl)
187 }
188
189 this.redirectService.redirectToLatestSessionRoute()
cb28bb92 190 },
1378c0d3
C
191
192 error: err => {
193 this.handleError(err)
194 this.isAuthenticatedWithExternalAuth = false
195 }
196 })
4a8d113b
C
197 }
198
199 private handleError (err: any) {
d12b40fb
C
200 if (this.authService.isOTPMissingError(err)) {
201 this.otpStep = true
202
203 setTimeout(() => {
204 this.form.get('otp-token').setValidators(USER_OTP_TOKEN_VALIDATOR.VALIDATORS)
205 this.otpTokenInput.focus()
206 })
207
208 return
209 }
210
9589907c
C
211 if (err.message.includes('credentials are invalid')) {
212 this.error = $localize`Incorrect username or password.`
213 return
214 }
215
216 if (err.message.includes('blocked')) {
217 this.error = $localize`Your account is blocked.`
218 return
219 }
220
221 if (err.body?.code === ServerErrorCode.ACCOUNT_WAITING_FOR_APPROVAL) {
222 this.error = $localize`This account is awaiting approval by moderators.`
223 return
224 }
225
226 if (err.body?.code === ServerErrorCode.ACCOUNT_APPROVAL_REJECTED) {
227 this.error = $localize`Registration approval has been rejected for this account.`
228 return
229 }
230
231 this.error = err.message
4a8d113b 232 }
b1794c53 233}