@ronas-it/angular-common v18.2.0
Ronas IT Angular Common
Common Angular services for communicating with backend, authentication and user managing.
Live demo
In progress...
About the library
Ronas IT Angular Common working with cookies. One of the main advantages of this approach is that cookies can be HTTP-only. It makes them read-protected on the client side, that improves safety against any Cross-site scripting (XSS) attacks. Cookie-based authentication allows using this services in Server-Side Rendering (SSR) applications.
Getting Started
Installation
Install Ronas IT Angular Common:
npm i @ronas-it/angular-common --saveUsage
ApiModule
- Add
ApiModuletoAppModuleimports:
import { ApiModule } from '@ronas-it/angular-common';
import { configuration } from '@configuration';
@NgModule({
imports: [
ApiModule.forRoot({
apiUrl: configuration.api.url
}),
...
],
...
})
export class AppModule { }- Inject
ApiServiceand use it:
import { ApiService } from '@ronas-it/angular-common';
import { Injectable } from '@angular/core';
@Injectable()
export class ProductService {
constructor(
private apiService: ApiService
) { }
public delete(id: number): Observable<void> {
return this.apiService.delete(`/products/${id}`);
}
...
}CookieModule
- Add
CookieModuletoAppModuleimports:
import { CookieModule } from '@ronas-it/angular-common';
@NgModule({
imports: [
CookieModule.forRoot({
defaultOptions: { path: '/', /* other cookie options ... */ }
}),
...
],
...
})
export class AppModule { }- Inject
CookieServiceand use it:
import { BehaviorSubject, Subject } from 'rxjs';
import { CookieService } from '@ronas-it/angular-common';
import { Injectable } from '@angular/core';
@Injectable()
export class CookiePopupFacade {
private isCookiesAccepted$: Subject<boolean>;
constructor(
private cookieService: CookieService
) {
this.isCookiesAccepted$ = new BehaviorSubject(this.cookieService.get('isCookiesAccepted') === 'true');
}
public acceptCookies(): void {
this.isCookiesAccepted$.next(true);
this.cookieService.put('isCookiesAccepted', 'true', { maxAge: 4e10 });
}
...
}- (SSR Only) Add providers for
REQUESTandRESPONSEinjection tokens from@nguniversal/express-engine/tokensinserver.ts:
server.get('*', (req, res) => {
res.render(indexHtml, {
req,
res,
providers: [
{
provide: APP_BASE_HREF,
useValue: req.baseUrl
},
{
provide: REQUEST,
useValue: req
},
{
provide: RESPONSE,
useValue: res
}
]
});
});- (SSR Only) Set
requestTokenandresponseTokenparameters in theCookieModuleconfig:
import { CookieModule } from '@ronas-it/angular-common';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
@NgModule({
imports: [
CookieModule.forRoot({
defaultOptions: { /* ... */ },
requestToken: REQUEST,
responseToken: RESPONSE
}),
...
],
...
})
export class AppModule { }UserModule
Note: This module depends on ApiModule and AuthModule. Please make sure to
install them prior to installing this module.
- Create a
Usermodel and extend it fromAbstractUser:
import { AbstractUser } from '@ronas-it/angular-common';
import { Expose } from 'class-transformer';
export class User extends AbstractUser {
@Expose({ groups: ['main'] })
public id: number;
@Expose({ groups: ['main'] })
public name: string;
@Expose({ groups: ['main'] })
public email: string;
}- Create a
UserServiceand extend it fromCommonUserService:
import { UserService as CommonUserService } from '@ronas-it/angular-common';
@Injectable()
export class UserService extends CommonUserService<User> {
/* Define custom methods or override existing methods here. */
}- Create a
UserModuleand addCommonUserModuleto imports:
import { NgModule } from '@angular/core';
import { User } from './models';
import { UserModule as CommonUserModule } from '@ronas-it/angular-common';
import { UserService } from './user.service';
@NgModule({
imports: [
CommonUserModule.forRoot({
userModel: User,
userService: UserService
}),
...
],
...
})
export class UserModule { }- Inject
UserServiceand use it:
import { Action } from '@ngrx/store';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { AuthService } from '@shared/auth';
import { catchError, filter, mergeMap, switchMap, withLatestFrom } from 'rxjs/operators';
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { User } from '../models';
import { userActions } from './actions';
import { UserService } from '../user.service';
@Injectable()
export class UserEffects {
public refreshProfile$: Observable<Action> = createEffect(
() => this.actions$.pipe(
ofType(userActions.refreshProfile),
withLatestFrom(this.authService.isAuthenticated$),
filter(([_, isAuthenticated]) => isAuthenticated),
switchMap(() => {
return this.userService.refreshProfile()
.pipe(
mergeMap((user: User) => [
userActions.updateProfile({ profile: user }),
userActions.refreshProfileSuccess()
]),
catchError((response: HttpErrorResponse) => of(userActions.refreshProfileFailure({ response })))
);
})
)
);
constructor(
private actions$: Actions,
private authService: AuthService,
private userService: UserService
) { }
}AuthModule
Note: This module depends on ApiModule, CookieModule and UserModule. Please make sure to
install them prior to installing this module.
- Create an
AuthServiceand extend it fromCommonAuthService:
import { AuthService as CommonAuthService } from '@ronas-it/angular-common';
import { Injectable } from '@angular/core';
import { User } from '@shared/user';
@Injectable()
export class AuthService extends CommonAuthService<User> {
/* Define custom methods or override existing methods here. */
}- Create an
AuthModuleand addCommonAuthModuleto imports:
import { AuthModule as CommonAuthModule } from '@ronas-it/angular-common';
import { AuthService } from './auth.service';
import { configuration } from '@configuration';
import { NgModule } from '@angular/core';
@NgModule({
imports: [
CommonAuthModule.forRoot({
unauthorizedRoutes: configuration.api.unauthorized_routes,
authService: AuthService,
// Optionally, you can pass `unauthenticatedRoute` parameter that
// specifies the route to redirect to after logout or when a user is
// not authenticated to view some page. By default it is set to `/login`.
unauthenticatedRoute: '/'
}),
...
],
...
})
export class AuthModule { }- Inject
AuthServiceand use it:
import { Action } from '@ngrx/store';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { authActions } from './actions';
import { AuthService } from '../auth.service';
import { catchError, exhaustMap, map } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
@Injectable()
export class AuthEffects {
public authorize$: Observable<Action> = createEffect(
() => this.actions$.pipe(
ofType(authActions.authorize),
exhaustMap((action) => {
return this.authService
.authorize(action.credentials)
.pipe(
map((response) => authActions.authSuccess({ response })),
catchError((response) => of(authActions.authFailure({ response })))
);
})
)
);
constructor(
private actions$: Actions,
private authService: AuthService
) { }
}API
ApiModule
Config
ApiModule.forRoot(config: ApiConfig)ApiConfig
| Name | Type | Required | Description |
|---|---|---|---|
apiUrl | string | Yes | Endpoint that allows you to access an API |
trailingSlash | boolean | No | The need for trailing slash (https://api.your-service.com/login/ for example) |
enableArrayKeys | boolean | No | Enabling array keys for http params |
fileKeys | Array<string> | No | List of the file keys for http params |
ApiService
| Field | Type |
|---|---|
apiUrl | string |
trailingSlash | string |
fileKeys | Array<string> |
| Method | Arguments | Return type |
|---|---|---|
get<T> | endpoint: string, params: any, options: object | Observable<T> |
post<T> | endpoint: string, data: any, options: object | Observable<T> |
put<T> | endpoint: string, data: any, options: object | Observable<T> |
delete<T> | endpoint: string, params: any, options: object | Observable<T> |
CookieModule
Config
CookieModule.forRoot(config: CookieConfig)CookieConfig
| Name | Type | Required | Description |
|---|---|---|---|
defaultOptions | CookieOptions | No | Cookie options that will be used if not specified in the put method |
requestToken | InjectionToken<Request> | No | Request injection token from @nguniversal/express-engine/tokens for cookies support in SSR |
responseToken | InjectionToken<Response> | No | Response injection token from @nguniversal/express-engine/tokens for cookies support in SSR |
CookieOptions
| Name | Type |
|---|---|
maxAge | number |
expires | Date |
path | string |
domain | string |
secure | boolean |
sameSite | boolean \| 'lax' \| 'strict' \| 'none' |
CookieService\
| Field | Type |
|---|---|
cookieString | string |
| Method | Arguments | Return type |
|---|---|---|
get | key: TKey | string \| null |
getObject | key: TKey | object \| null |
getAll | Record<string, string> | |
hasKey | key: TKey | boolean |
put | key: TKey, value: string, options?: CookieOptions | void |
putObject | key: TKey, value: object, options?: CookieOptions | void |
remove | key: TKey, options?: CookieOptions | void |
removeAll | options?: CookieOptions | void |
AuthModule
Config
CommonAuthModule.forRoot(config: AuthConfig)AuthConfig
| Name | Type | Required | Description |
|---|---|---|---|
unauthorizedRoutes | Array<string> | Yes | Routes that don't need authorization (public routes, e.g. login, registration and forgot password pages) |
authService | new (...args: Array<any>) => any | Yes | Service that will be used in your app |
unauthenticatedRoute | string | No | Route to redirect to after logout or when a user is not authenticated to view some page. By default it is set to /login |
disableRedirectAfterUnauthorize | boolean | No | Whether to redirect to unauthenticatedRoute after logout or when a user is not authenticated to view some page. By default it is set to false |
authenticatedRoute | string | No | Route to redirect after successful login |
loginEndpoint | string | No | Endpoint for login, e.g. /api/token |
refreshTokenEndpoint | string | No | Endpoint for refreshing token, e.g. /api/token/refresh |
refreshTokenEndpointMethod | 'get' \| 'post' | No | HTTP Method that will be used for calling endpoint to refresh token |
isAuthenticatedField | string | No | Field for cookie |
rememberField | string | No | Field for cookie |
cookiesExpirationDays | number | No | Expiration for authentication cookies when call authorize with remember flag set to true. By default it is set to 365 |
AuthService\
| Static constant | Type |
|---|---|
DEFAULT_LOGIN_ENDPOINT | string |
DEFAULT_UNAUTHENTICATED_ROUTE | string |
DEFAULT_IS_AUTHENTICATED_FIELD | string |
DEFAULT_REFRESH_TOKEN_ENDPOINT | string |
DEFAULT_REMEMBER_FIELD | string |
DEFAULT_COOKIES_EXPIRATION_DAYS | number |
| Field | Type |
|---|---|
isTokenRefreshing$ | Observable<boolean> |
isAuthenticated$ | Observable<boolean> |
cookiesExpiresDate | Date |
| Method | Arguments | Return type |
|---|---|---|
authorize<T> | credentials: AuthCredentials & T, remember: boolean | Observable<AuthResponse<User>> |
manuallyAuthorize | authResponse: object, remember: boolean = true | Observable<AuthResponse<User>> |
unauthorize | void | |
refreshToken | Observable<HttpResponse<void>> | |
setIsAuthenticated | remember: boolean | void |
resetIsAuthenticated | void | |
resetRemember | void |
AuthCredentials
| Field | Type | Required |
|---|---|---|
email | string | No |
password | string | Yes |
AuthResponse\
| Field | Type | Required |
|---|---|---|
user | User | No |
UserModule
Config
UserModule.forRoot(config: UserConfig)UserConfig
| Name | Type | Required | Description |
|---|---|---|---|
userModel | new (user: any) => any | Yes | Model (class) for user |
userService | new (...args: Array<any>) => any | Yes | Your UserService implementation |
profileRelations | Array<string> | No | Relations for getting profile request. For example: /profile?with[]=company&with[]=clients |
profileRelationsKey | string | No | with by default |
UserService\
| Field | Type |
|---|---|
profile$ | Observable<User> |
| Method | Arguments | Return type |
|---|---|---|
refreshProfile | Observable<User> | |
loadProfile | Observable<User> | |
updateProfile | user: User | Observable<void> |
updatePassword | userPasswords: UserPasswords | Observable<void> |
setProfile | user: User | void |
patchProfile | user: Partial<User> | void |
resetRemember | void | |
resetProfile | void | |
userToPlain | user: User, options?: ClassTransformOptions | Object |
plainToUser | plain: object, options?: ClassTransformOptions | User |
AbstractUser
| Field | Type | Required |
|---|---|---|
id | number \| string | Yes |
Contributing
Contributions to Ronas IT Angular Common are welcome. The contribution guide can be found in the Contributing guide.
License
Ronas IT Angular Common is open-sourced software licensed under the MIT license.
1 year ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago