npm package: @oitmain/angularedux-auth
Description: Angular Redux/Ngrx Auth Module // This package is still improving.
Latest version: 0.0.11

# @oitmain/angularedux-auth

Angular Redux/Ngrx Auth Module
// This package is still improving.

## Installation - After install node package
To get started, 
tsconfig.json in your application

```ts
// tsconfig.json
 "lib": [
      "es2017",
      "dom"
    ]
  },
  "include": [
    "src/**/*",
    "node_modules/@oitmain/angularedux-auth/lib/index.ts"
  ]
```
- Import AuthModule from your root module

```ts
import { AuthModule } from '@oitmain/angularedux-auth/lib'; 
```
and

```ts
imports: [
    ...
    AuthModule,
    ...
]
```

## Descriptions
- AuthService: Set Api service and address
- AuthEffects: Interaction between server side & client side
- AuthGuardService: Let only allowed-user can access specific page - You need to define 'canActive' feature in your routing module.

## Sample Skeleton template (In your template)
- How to import from reducer and define store in your container/component
```ts
/** For using Authentication */
import { Auth } from '@oitmain/angularedux-auth/lib';

/** For dispatching action to NGRX */
import { Store } from '@ngrx/store';
import * as rootReducer from '@oitmain/angularedux-auth/lib/reducers';
import * as authAction from '@oitmain/angularedux-auth/lib/actions/auth.action';

constructor( 
    // ...
    private store: Store<rootReducer.State>,
    private router: Router
) {}

ngOnInit() {
    this.userToken$ = this.store.select(rootReducer.getAuthUserToken);
    this.payload$ = this.store.select(rootReducer.getAuthPayload);

    /** Redirect to main application */
    this.isSignedIn_Subscription$ = (
        this.isSignedIn$ = this.store.select(rootReducer.getAuthIsSignedIn)).subscribe((val)=>{

        if(val) {
            this.router.navigate(['/app']);
        }
    });

    this.status_Subscription$ = (
        this.status$ = this.store.select(rootReducer.getAuthStatus)).subscribe((val)=>{

        if(val === 'Signin Success') {
            let signedUser: string;
            this.userToken$.subscribe((userToken)=>{
                signedUser = userToken;
            }).unsubscribe();

            /** For now, signedin keep alive for 25 hours  */
            localStorage.setItem('isExpiredAt',(Date.now() + 90000000).toString());
            localStorage.setItem('isSignedIn','true');
            localStorage.setItem('userToken',signedUser);
        }
    });

    if(localStorage.getItem('isSignedIn') === 'true') {
        if(parseInt(localStorage.getItem('isExpiredAt')) <= Date.now()) {
            localStorage.removeItem('isExpiredAt');
            localStorage.removeItem('isSignedIn');
            localStorage.removeItem('userToken');

            alert('Please Sign In Again!');
        } else {
            this.router.navigate(['/app']);
        }
    }
}

// ... Your code goes here
```
- For full skeleton code, go to github right below.
[https://github.com/withyuns/oitmain-Angularedux-Auth](https://github.com/withyuns/oitmain-Angularedux-Auth)

## Usage & Documentations
### 1. State tree from authState
- This module has Ngrx root state, so please use 'forFeature' for both Reducers & States

### 2. First step, authService to use API calls
- To use API call, you need to set both a service and an uri

```ts
/**
 * Logically, this should be called before any other API calls
 */
// In your appropriate page container - Maybe in your constructor OR ngOnInit
import { AuthService } from '@oitmain/angularedux-auth/lib';

constructor(
        // ...
        private authService: AuthService
) {
    authService.setService({
        name: 'graphcool',
        uri: 'YOUR_URI_FOR_AUTH',
        uriName: 'auth',
        isTokenAhead: false
    });
}

```

### 3. Change State manually by using ResetAuthAction
- Use ResetAuthAction when user's token still alive OR when you need to change previous state.
For example, I need to change state from 'Signin Fail' to 'Move Another Page'

```ts
// In ngOnDestroy() because you are exiting from current page
this.store.dispatch(new authAction.ResetAuthAction({
    isSignedIn: new Boolean(localStorage.getItem('isSignedIn')).valueOf(),
    userToken: localStorage.getItem('userToken'),
    status: 'Move Another Page',
    payload: 'Reset Auth Action'
}));
```

### 4. AuthGuardService
- You can use isSignedIn in AuthState when you need whether user signed in.
- However, AuthGuardService handle both localStorage & AuthState, so please use the service when you need a guard for limited page in your router module.

## For Debug purpose
- Use @ngrx/store-devtools
(You don't need to install this package - It's already in this package)
```ts
// In you module
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';
...
imports: [
    // ...
    !environment.production ? StoreDevtoolsModule.instrument({ maxAge: 50 }) : []
],
```

## Updates
(Version 0.0.10~11)
- Removed all successful status, use 'Token' directly.
- Now status has following: You can use this in your components or views.

| value          | string of status             |
|----------------|------------------------------|
| INIT           | 'auth-status-init'           |
| GET_TOKEN_FAIL | 'auth-status-get-token-fail' |
| SIGNIN_FAIL    | 'auth-status-signin-fail'    |
| SIGNUP_FAIL    | 'auth-status-signup-fail'    |

```html
    <!-- In your html view -->
<auth-signin 
    [status]='status$ | async'
></auth-signin>
    <!-- ... -->
<div *ngIf="status === 'auth-status-signin-fail'">
    <!-- Your view action when signin fails -->
</div>
```
or
```ts
    // In your typescript component
import { AuthStatus } from '@oitmain/angularedux-auth/lib';
    // ...

(this.store.select(rootReducer.getAuthStatus)).subscribe((res)->{
    if(res === AuthStatus.SIGNIN_FAIL) {
        // Your action when signin fails
    }
});
```

(Version 0.0.9)
- Improved signout: Once it signout, then all state and action is reset.
- To use this, just call signout action.

```ts
this.store.dispatch(new authAction.SignOutAction);
```

(Version 0.0.8)
- Now it's possible to use 'Get Token ahead Signin'
- Flow: (Get Token) -> (Try to signin using your token name)
- This action calls 2 Apis, and it is more flexible to use (using tokenName...etc)
```ts
this.store.dispatch(new authAction.GetTokenAheadSigninAction({
    apiForSignin: 'API_FOR_SIGNIN',
    apiForToken: 'API_FOR_GET_TOKEN',
    tokenName: 'YOUR_TOKEN_NAME',
    headers: {
        'Content-Type':'application/x-www-form-urlencoded',
        'Access-Control-Allow-Origin':'*'
    },
    params: {
        'username': id_from_view,
        'password': pwd_from_view
    }
}));
```
- Important! This action doesn't call Signin Success, this calls either Signin Result or Signin Fail, so please call Signin Success in your module. (Of course, this action calls GetTokenFail action if some error happened as it creates a token)

## References
- @ngrx/store