티스토리 뷰
Angular : Email Client - 1-8. 인증모듈작성 - 가입하기와 로그인 로직 작성하기
Korean Eagle 2020. 6. 23. 23:291. 이 포스트는 Email Client를 작성하는 시리즈의 일부이다
1-1 지금까지 부가적인 기능들을 추가했는데 이번에는 가입하기와 로그인 기능을 구현한다.
2. 가입하기 구현하기
2-1 가입하기는 post로 전달하며 url은 https://api.angular-email.com/auth/signup 이다.
2-2 중복된 username인 경우 { username: string } 형식의 데이터와 422 코드를 돌려준다. 값은 'usename in use'
2-3 정상인 경우에도 { username; string } 형식을 반납하는데 200 코드이다. 여기서는 가입한 username이 들어간다.
3. 이제 필요한 것은 다 알았으니 가입하기를 구현한다.
3-1 sign up template에서 form에 ngSubmit 이벤트 발생 시 onSubmit을 실행하도록 하였다.
<h1 class="my-5">Create an Account</h1>
<form class="col-sm-8" [formGroup]="registrationGroup" (ngSubmit)="onSubmit()">
<div class="form-group">
<label class="form-label" for="username">Username</label>
<input id="username" class="form-control" type="text" formControlName="username">
<app-validation-message [control]="registrationGroup.get('username')"></app-validation-message>
</div>
<div class="form-group">
<label class="form-label" for="password">Password</label>
<input id="password" class="form-control" type="password" formControlName="password">
<app-validation-message [control]="registrationGroup.get('password')"></app-validation-message>
</div>
<div class="form-group">
<label class="form-label" for="passwordConfirmation">Password Confirmation</label>
<input id="passwordConfirmation" class="form-control" type="password" formControlName="passwordConfirmation">
<app-validation-message [control]="registrationGroup.get('passwordConfirmation')"></app-validation-message>
<app-validation-message [control]="registrationGroup"></app-validation-message>
</div>
<div class="my-4">
<button type="submit" class="btn btn-secondary mr-2" [disabled]="!registrationGroup.valid">Submit</button>
<button type="reset" class="btn btn-warning">Reset</button>
</div>
</form>
3-2 sign up 클래스에 onSubmit을 구현한다.
3-2-1 onSubmit에서 auth 서비스의 signup을 호출하면서 필요한 정보를 다 넘겨준다.
3-2-2 200번 코드로 가입 성공하면 inbox 페이지로 이동하도록 하고,
3-2-3 실패한 경우는 422코드가 반환되고 결과 값에 따라서 다양한 에러 값들을 설정하여 문제가 무엇인지 알려준다.
3-2-3-1 여기서는 있어야 하는 데이터가 없는 경우 인터넷 연결 없음, 중복의 경우 중복에러를 세팅한다.
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { AuthValidators } from '../validators/auth-validators';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css'],
})
export class SignUpComponent implements OnInit {
registrationGroup: FormGroup;
constructor(
private formBuilder: FormBuilder,
private authService: AuthService,
private router: Router
) {}
ngOnInit(): void {
this.registrationGroup = this.formBuilder.group(
{
username: [
'',
[
Validators.required,
Validators.minLength(4),
Validators.maxLength(20),
], AuthValidators.checkUniqueUsername(this.authService)
],
password: [
'',
[
Validators.required,
Validators.minLength(4),
Validators.maxLength(20),
],
],
passwordConfirmation: [
'',
[
Validators.required,
Validators.minLength(4),
Validators.maxLength(20),
],
],
},
{
validators: AuthValidators.checkPasswordMatch(
'password',
'passwordConfirmation'
),
}
);
}
onSubmit() {
this.authService.signUp({
username: this.registrationGroup.value['username'],
password: this.registrationGroup.value['password'],
passwordConfirmation: this.registrationGroup.value['passwordConfirmation'],
}).subscribe(
() => this.router.navigateByUrl("/inbox"),
(err) => {
console.log(err);
if (err.error.username) {
this.registrationGroup.setErrors({ duplication: true })
} else {
this.registrationGroup.setErrors({ noInternet: true })
}
}
)
}
}
3-3 auth 서비스에서 signup 메소드를 작성한다.
3-3-0 가입과 로그인에 사용될 인터페이스를 AuthResponse 파일에 추가한다.
export class AuthResponses {
}
export interface AuthCredential {
username: string
password: string
passwordConfirmation: string
}
export interface LoginCredential {
username: string,
password: string
}
3-3-1 post로 가입 정보를 넣어 http로 전송한다.
3-3-1-1 성공했을 경우 tap을 통해 로그인 유저이름과 현재 로그인 상태인 것을 signedIn$구독자에게 알려준다.
3-3-1-2 Inbox페이지로의 이동은 sign up 컴포넌트에서 구독하는 곳에서 처리하였다.
3-3-1-2 실패했을 때도 실패 코드도 sign up 컴포넌트에서 이미 처리하였다.
signUp(crediential: AuthCredential): Observable<SignUpResponse> {
return this.http.post<SignUpResponse>(`${this.url}/signup`, crediential).pipe(
tap(({username})=> {
this.username = username
this.signedIn$.next(true)
})
)
}
3-4 결과화면 - 가입에 성공하면 inbox 페이지가 열리고 sign out이 화면에 나오게 된다.
3-4-1 inbox가 열린다는 의미는 guard도 통과했다는 말이다.
4. 이번에는 로그인 기능을 구현하기 위한 기본 정보이다.
4-1 로그인은 post 메소드로 요청하며 url은 https://api.angular-email.com/auth/signin 이다.
4-2 username, password를 전송하게 되며,
4-3 성공시에는 200번 코드로 { username: string } 형식이 반환되며 username은 로그인 성공한 username이다.
4-4 실패시에는 422번 코드가 반환되며 아이디가 없는 경우 { username: string, password: string } 형식이 반환된다.
4-4-1 아이디가 있지만 비밀번호가 안맞으면 422번 코드로 { password: string } 형식이 반환된다.
5. 로그인을 작성한다.
5-1 우선 sign in 컴포넌트에서 ngSubmit 이벤트를 수신한 경우 onSubmit이 실행되도록 작성하였다.
5-1-1 자세히 보면 로그인 버튼 위에 검증 메시지 컴포넌트가 2개가 있는데
5-1-2 로그인에 실패했을 때 메시지를 보여주기 위해서 추가한 부분이다. form group을 넘기고 있음에 주의한다.
<h1 class="my-5">Log In</h1>
<form class="col-sm-8" [formGroup]="loginGroup" (ngSubmit)="onSubmit()">
<div class="form-group">
<label class="form-label" for="username">Username</label>
<input id="username" class="form-control" type="text" formControlName="username">
<app-validation-message [control]="loginGroup.get('username')"></app-validation-message>
</div>
<div class="form-group">
<label class="form-label" for="password">Password</label>
<input id="password" class="form-control" type="password" formControlName="password">
<app-validation-message [control]="loginGroup.get('password')"></app-validation-message>
<app-validation-message [control]="loginGroup"></app-validation-message>
</div>
<div class="my-3">
<button type="submit" class="btn btn-secondary mr-2" [disabled]="!loginGroup.valid">Submit</button>
<button type="reset" class="btn btn-warning">Reset</button>
</div>
</form>
5-2 sign in 컴포넌트에서 onSubmit을 구현한다.
5-2-1 authService를 주입받아서 username, password를 전달하면서 signin 메소드를 호출하고 있다.
5-2-2 성공한 경우 inbox로 이동하는 코드가 있다.
5-2-3 실패한 경우 유저이름을 못찾은 경우, 비밀번호가 안맞는 경우, 네트워크 오류인 경우로 에러처리 하였다.
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.css']
})
export class SignInComponent {
loginGroup: FormGroup
constructor(
private formBuilder: FormBuilder,
private authService: AuthService,
private router: Router
) {
this.loginGroup = this.formBuilder.group({
username: ['', [
Validators.required,
Validators.minLength(4),
Validators.maxLength(20)
]],
password: ['', [
Validators.required,
Validators.minLength(4),
Validators.maxLength(20)
]],
})
}
onSubmit() {
this.authService.signIn({
username: this.loginGroup.value['username'],
password: this.loginGroup.value['password']
}).subscribe(
() => this.router.navigateByUrl('/inbox'),
(err) => {
console.log(err);
if (err.error.password && err.error.username) {
this.loginGroup.setErrors({ usernameNotFound: true })
} else if (err.error.password) {
this.loginGroup.setErrors({ wrongPassword: true })
} else {
this.loginGroup.setErrors({ noInternet: true })
}
}
)
}
}
5-3 이제 auth 서비스의 signin 메소드를 작성한다.
5-3-1 위에서 부분 코드를 넣었으니 여긴 최종 코드들 다 넣었다.
5-3-2 로직은 가입하기와 거의 동일하다.
5-3-2-1 다만 결과데이터의 속성이 경우마다 다르므로 Observable<any>로 처리했다.
5-3-2-2 class로 처리하면 더 명확하긴 하지만 그냥 넘어간다.
5-3-2-3 성공하면 username을 저장하고 로그인 상태변화를 signedIn$으로 전송한다.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators'
import { AuthCredential, LoginCredential } from './auth-responses';
@Injectable({
providedIn: 'root'
})
export class AuthService {
signedIn$ = new BehaviorSubject<boolean>(null)
username: string = ''
url = 'https://api.angular-email.com/auth'
constructor(private http: HttpClient) { }
signedIn(): Observable<SignedInResponse> {
return this.http.get<SignedInResponse>(`${this.url}/signedIn`).pipe(
tap((response: SignedInResponse)=> {
this.username = response.username
this.signedIn$.next(response.authenticated)
})
)
}
signUp(crediential: AuthCredential): Observable<SignUpResponse> {
return this.http.post<SignUpResponse>(`${this.url}/signup`, crediential).pipe(
tap(({username})=> {
this.username = username
this.signedIn$.next(true)
})
)
}
signIn(crediential: LoginCredential): Observable<any> {
console.log(crediential);
return this.http.post(`${this.url}/signin`, crediential).pipe(
tap(({username}) => {
this.username = username
this.signedIn$.next(true)
})
)
}
checkDuplication(username: string) {
return this.http.post(`${this.url}/username`, { username })
}
}
interface SignedInResponse {
authenticated: boolean,
username: string
}
interface SignUpResponse {
username: string
}
5-4 결과화면 - 로그인 실패화면이다. 비밀번호가 안맞다고 나온다. 성공하면 sign up과 결과화면이 동일하다.
'Demos > Email Client' 카테고리의 다른 글
Angular : Email Client - 1-10. 인증모듈작성 - 로그아웃 (0) | 2020.06.24 |
---|---|
Angular : Email Client - 1-9. 인증모듈작성 - 쿠키 관리 (0) | 2020.06.24 |
Angular : Email Client - 1-7. 인증모듈작성 - 검증 에러 메시지 보여주기 (0) | 2020.06.23 |
Angular : Email Client - 1-6. 인증모듈작성 - 비동기 검증로직을 사용한 username 중복 확인 및 Password Validator 작성 (0) | 2020.06.23 |
Angular : Email Client - 1-5. 인증모듈작성 - Sign up, Sign in Template과 Form Control 작성하기 (0) | 2020.06.22 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- hibernate
- 스프링부트
- form
- 스프링
- 자바
- jsp
- Security
- mapping
- Angular
- 하이버네이트
- 설정하기
- Spring Security
- Many-To-Many
- 외부파일
- Rest
- 설정
- XML
- crud
- spring boot
- login
- one-to-one
- MYSQL
- RestTemplate
- 상속
- Validation
- one-to-many
- 매핑
- Spring
- 로그인
- WebMvc