@notiz/nest-auth-formly
v0.2.0
Published
Nest Auth UI with TailwindCSS and Formly for Angular
Downloads
16
Readme
NestAuthFormly
Works together with nest-auth
Installation
Requires Tailwind, Tailwind Forms Plugin, Formly and Tailwind-Formly
# select forms plugin
ng add ngx-tailwind
# alternative install via
npm install -D @tailwindcss/forms
ng add @ngx-formly/schematics
# or
npm i @ngx-formly/core
npm i @notiz/formly-tailwindcss
Your AppModule
should look like this and import HttpClientModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';
import { FormlyModule } from '@ngx-formly/core';
import { FormlyTailwindcssModule } from '@notiz/formly-tailwindcss';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormlyModule.forRoot({
extras: { lazyRender: true },
}),
FormlyTailwindcssModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Now install ... NOT YET AVAILABLE
Nest Application works great with code generators such as ng-openapi-gen for Rest or graphql-code-generator for GraphQL to create Angular services for your endpoints.
Usage
NestAuthFormlyModule
Import NestAuthFormlyModule
which includes JwtInterceptor
, read more about Interceptor.
import { environment } from '@env/environment';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { FormlyModule } from '@ngx-formly/core';
import { FormlyTailwindcssModule } from '@notiz/formly-tailwindcss';
import { NestAuthFormlyModule } from '@notiz/nest-auth-formly';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormlyModule.forRoot({
extras: { lazyRender: true },
validationMessages: [{ name: 'required', message: 'Is required' }],
}),
FormlyTailwindcssModule,
HttpClientModule,
NestAuthFormlyModule.forRoot({
httpInterceptor: {
// attaches access token only to the allowed endpoints
allowedList: [
// `${environment.baseUrl}/users/me`,
// `${environment.baseUrl}/graphql`,
`${environment.baseUrl}/*`,
],
},
}),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Social Login
To add social login buttons via formly import SocialLoginModule
to register formly type socialLogin
.
import { environment } from '@env/environment';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { FormlyModule } from '@ngx-formly/core';
import { FormlyTailwindcssModule } from '@notiz/formly-tailwindcss';
import { NestAuthFormlyModule } from '@notiz/nest-auth-formly';
import { SocialLoginModule } from '@notiz/nest-auth-formly/social';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormlyModule.forRoot({
extras: { lazyRender: true },
validationMessages: [{ name: 'required', message: 'Is required' }],
}),
FormlyTailwindcssModule,
HttpClientModule,
NestAuthFormlyModule,
SocialLoginModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Interceptor
JwtInterceptor
adds the access token, if available, to the request as Authorization Bearer token.
Import NestAuthFormlyModule
or add JwtInterceptor
as a provider
import { environment } from '@env/environment';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';
import { FormlyModule } from '@ngx-formly/core';
import { FormlyTailwindcssModule } from '@notiz/formly-tailwindcss';
import { JwtInterceptor } from '@notiz/nest-auth-formly';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormlyModule.forRoot({
extras: { lazyRender: true },
validationMessages: [{ name: 'required', message: 'Is required' }],
}),
FormlyTailwindcssModule,
HttpClientModule,
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
],
bootstrap: [AppComponent],
})
export class AppModule {}
Guards
AuthGuard
protects your routes from not authenticated users.
import { AuthGuard } from '@notiz/nest-auth-formly';
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{
path: 'login',
loadChildren: () =>
import('./auth/login/login.module').then((m) => m.LoginModule),
},
{
path: 'dashboard',
loadChildren: () =>
import('./dashboard/dashboard.module').then((m) => m.DashboardModule),
canActivate: [AuthGuard],
},
];
Customize Guard behavior
Customize the behavior of AuthGuard
by passing an rxJS pipe through the route data's authGuardPipe
key.
The following pre-built pipes are available:
| Pipes | Description |
| ------------------------ | -------------------------------------------------------------- |
| loggedIn
| The default pipe, rejects if the user is not authenticated |
| hasRole
| Rejects authenticated users without specific role |
| hasRoleOf
| Rejects authenticated users without one of the specified roles |
| emailVerified
| Rejects authenticated users without verified email |
| redirectLoggedInTo
| Redirect authenticated users to a different route |
| redirectUnauthorizedTo
| Redirect unauthenticated users to a different route |
Example use:
import {
AuthGuard,
loggedIn,
redirectLoggedInTo,
redirectUnauthorizedTo,
} from '@notiz/nest-auth-formly';
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{
path: 'login',
loadChildren: () =>
import('./auth/login/login.module').then((m) => m.LoginModule),
canActivate: [AuthGuard],
data: { authGuardPipe: () => redirectLoggedInTo(['']) },
},
{
path: 'profile',
loadChildren: () =>
import('./profile/profile.module').then((m) => m.ProfileModule),
canActivate: [AuthGuard],
data: { authGuardPipe: () => loggedIn }, // Default behavior of AuthGuard
},
{
path: 'dashboard',
loadChildren: () =>
import('./dashboard/dashboard.module').then((m) => m.DashboardModule),
canActivate: [AuthGuard],
data: { authGuardPipe: () => redirectUnauthorizedTo(['login']) },
},
{
path: 'admin',
loadChildren: () =>
import('./admin/admin.module').then((m) => m.AdminModule),
canActivate: [AuthGuard],
data: { authGuardPipe: () => hasRole('ADMIN') },
},
];
Use canActivate
helper and spread syntax to make your routes more readable:
import {
AuthGuard,
canActivate
loggedIn,
redirectLoggedInTo,
redirectUnauthorizedTo,
} from '@notiz/nest-auth-formly';
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{
path: 'login',
loadChildren: () =>
import('./auth/login/login.module').then((m) => m.LoginModule),
...canActivate(() => redirectLoggedInTo(['']))
},
{
path: 'profile',
loadChildren: () =>
import('./profile/profile.module').then((m) => m.ProfileModule),
...canActivate(() => loggedIn([''])) // Default behavior of AuthGuard
},
{
path: 'dashboard',
loadChildren: () =>
import('./dashboard/dashboard.module').then((m) => m.DashboardModule),
...canActivate(() => redirectUnauthorizedTo(['login'])),
},
{
path: 'admin',
loadChildren: () =>
import('./admin/admin.module').then((m) => m.AdminModule),
...canActivate(() => hasRole('ADMIN')),
},
];
Compose your own pipes
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { canActivate, hasRole } from '@notiz/nest-auth-formly';
import { pipe } from 'rxjs';
const adminOnly = pipe(hasRole('ADMIN'));
const routes: Routes = [
...{
path: 'admin',
loadChildren: () =>
import('./admin/admin.module').then((m) => m.AdminModule),
...canActivate(() => adminOnly),
},
];
Using router state
const onlyAllowSelf = (next) =>
map((user) => !!user && next.params.userId === user.id);
Development
Start the demo of nest-auth
npm i
ng s
# generate rest
npm run codegen:rest
# generate graphql
npm run codegen:graphql