I'm trying to build this simple MEAN stack app with the simple functionality of registering, login in and then viewing the profile.
So, where does the error occur? It pops up when this newbie coder tries to log in to this simple app
Here's a screenshot of it
Here are the codes for you to see the errors that I might have made.
This is the code belonging to the login component
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router'
import { FlashMessagesService } from 'angular2-flash-messages';
import { Observable } from 'rxjs/Rx';
import { map, subscribeOn } from 'rxjs/operators';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
username: String;
password: String;
constructor(
private authService: AuthService,
private router: Router,
private flashMessage: FlashMessagesService
) { }
ngOnInit(): void {
}
onLoginSubmit() {
console.log(this.username, this.password);
const user = {
username: this.username,
password: this.password
}
this.authService.authenticateUser(user).subscribe(data => {
console.log(data);
if (data) {
this.authService.storeUserData(data.token, data.user);
this.flashMessage.show('You are now logged in', {
cssClass: 'alert-success',
timeout: 5000
});
this.router.navigate(['/dashboard']);
}
else {
this.flashMessage.show('incorrect information you stupidass', {
cssClass: 'alert-danger',
timeout: 5000
});
this.router.navigate(['/login']);
}
});
}
}
The next one is of the authentication service file
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { map } from 'rxjs/operators';
import { tokenNotExpired } from 'angular2-jwt';
#Injectable({
providedIn: 'root'
})
export class AuthService {
authToken: any;
user: any;
constructor(private http: Http) { }
registerUser(user: { name: String; email: String; username: String; password: String; }) {
let headers = new Headers();
//adding a value to the header and connecting to the backend
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:3000/users/register', user, { headers: headers }).pipe(map((res: { json: any; }) => res.json));
}
authenticateUser(user: { username: String; password: String; }) {
let headers = new Headers();
//adding a value to the header and connecting to the backend
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:3000/users/authenticate', user, { headers: headers }).pipe(map((res: { json: any; }) => res.json));
}
getProfile() {
let headers = new Headers();
this.loadToken();
headers.append('Authroization', this.authToken);
//adding a value to the header and connecting to the backend
headers.append('Content-Type', 'application/json');
return this.http.get('http://localhost:3000/users/profile', { headers: headers }).pipe(map((res: { json: any; }) => res.json));
}
storeUserData(token, user) {
localStorage.setItem('id_token', token);
localStorage.setItem('user', JSON.stringify(user));
this.authToken = token;
this.user = user;
}
loadToken() {
const token = localStorage.getItem('id_token');
this.authToken = token;
}
loggedIn() {
return tokenNotExpired(null, localStorage.getItem('id_token'));
}
logout() {
this.authToken = null;
this.user = null;
localStorage.clear();
}
}
//this.myObservable().pipe(map(data => {}))
And this last one is of the app.component file
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { RouterModule, Routes } from '#angular/router';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { LoginComponent } from './components/login/login.component';
import { RegisterComponent } from './components/register/register.component';
import { HomeComponent } from './components/home/home.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { ProfileComponent } from './components/profile/profile.component';
import { JwtModule } from '#auth0/angular-jwt';
import { FormsModule } from '#angular/forms';
import { ValidateService } from './services/Validate.service';
import { FlashMessagesModule } from 'angular2-flash-messages';
import { AuthService } from './services/auth.service';
import { AuthGuard } from './guards/auth.guard';
export function tokenGetter() {
return localStorage.getItem('access_token');
}
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'login', component: LoginComponent },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
{ path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
]
#NgModule({
declarations: [
AppComponent,
NavbarComponent,
LoginComponent,
RegisterComponent,
HomeComponent,
DashboardComponent,
ProfileComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot(appRoutes),
FlashMessagesModule.forRoot(),
JwtModule.forRoot({
config: {
tokenGetter: tokenGetter,
whitelistedDomains: ['localhost:4000'],
blacklistedRoutes: ['localhost:4000/api/auth']
}
})
],
providers: [ValidateService, AuthService, AuthGuard],
bootstrap: [AppComponent]
})
export class AppModule { }
Why does this error occur?
Edit: Below are the screenshot of postman requests that I did for this app. There you can find the value of the token as well.
The authentication request is what you see here:
This next one is for the get request done to get into the profile:
Related
I am trying to use jsonwebtoken with NestJs, and have been battling with this issue whereby NestJS returns an empty object once it encouters my code line to generate a token.
Each time, I try to generate a token, the server simply responds with an empty object.
Here is my jwt strategy code for passport
import { ConfigService } from "#nestjs/config";
import { ExtractJwt, Strategy } from "passport-jwt";
import { PassportStrategy } from "#nestjs/passport";
import { Inject, Injectable, UnauthorizedException } from "#nestjs/common";
import { RidersService } from "../riders/riders.service";
import { DriversService } from "../drivers/drivers.service";
#Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly riderService: RidersService,
private readonly driverService: DriversService,
#Inject(ConfigService) config: ConfigService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: config.get("JWT_SECRET"),
});
}
async validate(payload: {
role: string;
iat: number;
exp: number;
phone: string;
}) {
if (!payload) {
throw new UnauthorizedException();
}
const service = {
rider: this.riderService,
driver: this.driverService,
};
const user = await service[payload.role].findByAny(payload.phone);
if (!user) {
throw new UnauthorizedException();
}
// eslint-disable-next-line #typescript-eslint/no-unused-vars
const { iat, exp, ...rest } = payload;
return rest;
}
}
Now here is my AuthService stripped off
import { InjectModel } from "#nestjs/mongoose";
import { Injectable, Logger, HttpException } from "#nestjs/common";
import { JwtService } from "#nestjs/jwt";
#Injectable()
export class AuthService {
private readonly logger = new Logger(AuthService.name);
constructor(
private readonly jwtService: JwtService,
) {}
async register(
phone: string,
role: string,
): Promise<LoginResponseDTO | GENERIC_RESPONSE | unknown> {
return {
token: this.jwtService.sign({ role, phone }),
};
}
}
This line return { token: this.jwtService.sign({ role, phone }), } returns an empt object {} no matter what I do, once the code execution gets there, it stops and sends back an empty response.
Here is my Authmodule stripped off
import { JwtStrategy } from "./jwt.strategy";
import { Module } from "#nestjs/common";
import { AuthService } from "./auth.service";
import { AuthController } from "./auth.controller";
import { PassportModule } from "#nestjs/passport";
import { JwtModule } from "#nestjs/jwt";
import { ConfigModule, ConfigService } from "#nestjs/config";
#Module({
imports: [
PassportModule,
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
secret: configService.get<string>("JWT_SECRET"),
signOptions: { expiresIn: configService.get<string>("JWT_EXPIRESIN") },
}),
inject: [ConfigService],
}),
],
providers: [
AuthService,
JwtStrategy,
],
exports: [AuthService],
controllers: [AuthController],
})
export class AuthModule {}
Here is my Authcontroller stripped off
import { AuthService } from "./auth.service";
import { BadRequestException, Controller, Post, Query } from "#nestjs/common";
import { ParsePhonePipe } from "./../pipes/transform-phone.pipes";
#Controller("auth")
export class AuthController {
constructor(private readonly authService: AuthService) {}
#Post("signup")
async register(
#Query("phone", new ParsePhonePipe()) phone: string,
#Query("role") role: string,
) {
if (!role) {
throw new BadRequestException("user role is missing");
}
try {
const response = await this.authService.register(phone, role);
console.log(response, "RESPONSE");
return response;
} catch (error) {
return error;
}
}
}
Here is Appmodule stripped of
import { ConfigModule, ConfigService } from "#nestjs/config";
import { Module } from "#nestjs/common";
import { APP_GUARD } from "#nestjs/core";
import { AuthModule } from "./auth/auth.module";
import { JwtAuthGuard } from "./auth/jwt.auth.guard";
#Module({
imports: [
AuthModule,
MongooseModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
uri: configService.get<string>("RYDR_DB_URI"),
}),
inject: [ConfigService],
}),
ConfigModule.forRoot({
isGlobal: true,
}),
],
providers: [
{
provide: APP_GUARD,
useClass: JwtAuthGuard,
},
TripHistoryService,
DriversService,
],
})
export class AppModule {}
The login response has nothing to do with the jwt as there are three possible response types defined.
I am unable to generate jwt token and it simply exit with an empty object {}, there is no error whatsoever.
What might I be doing wrong?
I tried to use jsonwebtoken package itself, expecting that there might be an issue with NestJs but it still failed to generate any token instead it returned an empty object as a response.
so just new with angular and firebase, i am trying to create authentication, the code is not throwing any error but when i try accessing it in the browser it freezes, i can't even click on anything. below are the authentication code.
import { Injectable, NgZone } from '#angular/core';
import { AngularFireAuth } from '#angular/fire/compat/auth';
import { AngularFirestore, AngularFirestoreDocument } from '#angular/fire/compat/firestore';
import { Router } from '#angular/router';
import * as auth from 'firebase/auth';
import { UserService } from '../users/user.service';
//import { User } from '../../models/users/user';
import { DataService } from '../database/data.service';
#Injectable({
providedIn: 'root'
})
export class AuthService {
loggedin = false;
// user$: Observable<any> | undefined;
// user: any;
userData: any;
constructor(
public firestore: AngularFirestore,
public fireauth: AngularFireAuth,
public userservice: UserService,
public router: Router,
public ngZone: NgZone,
public dataService: DataService,
) {
// this.fireauth.authState.subscribe((user) => {
// if (user){
// this.userData = user;
// this.dataService.addData('users', this.userData); // you can json stringify this if you want
// localStorage.setItem('user', JSON.stringify(this.userData));
// JSON.parse(localStorage.getItem('user') || '{}');
// }
// else {
// this.dataService.addData('users', null);
// localStorage.setItem('user', '');
// JSON.parse(localStorage.getItem('user') || '{}');
// }
// });
//this.loggedin = !!localStorage.getItem('user');
}
// Sign in with email/password
async loginUser(email: string, password: string) {
try {
const result = await this.fireauth
.signInWithEmailAndPassword(email, password);
this.SetUserData(result.user);
this.fireauth.authState.subscribe((user_1) => {
if (user_1) {
this.router.navigate(['dashboard']);
}
});
} catch (error) {
window.alert(error);
}
}
i have comment out eveery code int he login components but i still get this issue,
app.modules
#NgModule({
declarations: [
AppComponent,
LoginComponent,
OrderListComponent,
DashboardComponent,
ProfileGeneralComponent,
MenuComponent,
ProfileMenuComponent,
ProfileServicesComponent,
Dashboard2Component,
LineChartComponent,
],
imports: [
BrowserModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
AppRoutingModule,
IonicStorageModule.forRoot(),
IonicModule.forRoot({
mode: 'ios'
}),
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
AngularFirestoreModule,
AngularFireStorageModule,
AngularFireDatabaseModule,
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAuth(() => getAuth()),
provideFirestore(() => getFirestore()),
provideStorage(() => getStorage()),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module
const routes: Routes = [
{ path: '', component: LoginComponent },
{
path: 'dashboard',
//canActivate: [AuthGuard],
component: DashboardComponent
},
{
path: 'overview-dashboard',
canActivate: [AuthGuard],
component: Dashboard2Component
},
{
path: 'profile',
canActivate: [AuthGuard],
component: ProfileGeneralComponent
},
{
path: 'profile-menu',
canActivate: [AuthGuard],
component: ProfileMenuComponent
},
{
path: 'profile-services',
canActivate: [AuthGuard],
component: ProfileServicesComponent
},
{
path: 'order-list',
canActivate: [AuthGuard],
component: OrderListComponent
},
{
path: 'login',
canActivate: [AuthGuard],
component: LoginComponent
},
{
path: 'line-chart',
canActivate: [AuthGuard],
component: LineChartComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
when i access other pages with nothing related to authentication they work.
I have an Angular app which requires session authorization from an OIDC service. With the normal/happy path, a separate NodeJS/Express app checks for session authorization and redirects to the OIDC authorization/authentication service and attaches the relevant headers. If everything passes, the middleware routes to the Angular app.
At a point though, the Angular app runs with a token that is expired. The Angular app gets the username and at that point I could check for expiration. However, if it is expired, I need the Angular way to react to the error condition by re-routing the whole Angular app to the relevant middleware page. Because the indicator will go to a component nested within the app, I don't know how to get the little component to redirect the bigger/encompassing app.
I'm not an Angular person, so I don't even know what part of Angular to look up. Because of my lack of knowledge, I'm including source files that might or might not be relevant.
header.component.ts is where it gets the username and could return a bad token indicator
import { Component, OnInit } from '#angular/core';
import { ProfileService } from '../../../core/services/profile.service';
#Component({
selector: 'header-comp',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
userName: string = 'No Session';
constructor(private profileService: ProfileService) { }
ngOnInit() {
this.onDisplayUserLogged();
}
onDisplayUserLogged() {
this.profileService.getUsername().subscribe(data => {
this.userName = 'Welcome: ' + data;
});
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { APP_BASE_HREF } from '#angular/common';
import { Router } from '#angular/router';
//Services
import { ProfileService } from './core/services/profile.service';
import { FinanceService } from './core/services/finance.service';
import { CmasService } from './core/services/cmas.service';
import { SoftlayerService } from './core/services/softlayer.service';
import { DashboardService } from './core/services/dashboard.service';
import { LowDollarExceptionService } from './core/services/lowDollarException.service';
//Components
import { AppComponent } from './app.component';
import { CmasComponent } from './modules/cmas/cmas.component';
import { SoftlayerComponent } from './modules/softlayer/softlayer.component';
import { FinanceComponent } from './modules/finance/finance.component';
import { ErrorComponent } from './modules/error/error/error.component';
import { LowDollarExceptionComponent } from './modules/lowDollarException/lowDollarException.component'
import { MenuComponent } from './shared/layout/menu/menu.component';
import { BasicComponent } from './shared/modals/basic/basic.component';
import { HeaderComponent } from './shared/layout/header/header.component';
import { PreProcessedPipe } from './shared/components/file-listing/file-listing.component';
import { ProcessedPipe } from './shared/components/softlayer-file-list/softlayer-file-list.component';
//Routing
import { AppRoutingModule } from './app-routing.module';
//Libs
import { AuthInterceptor } from 'auth-lib';
import { TermsComponent } from './modules/terms/terms.component';
import { FileListingComponent } from './shared/components/file-listing/file-listing.component';
import { ConfirmCancelComponent } from './shared/modals/confirm-cancel/confirm-cancel.component';
import { ErrorDisplayComponent } from './shared/components/error-display/error-display.component';
import { AboutComponent } from './modules/about/about.component';
import { ResultsComponent } from './modules/cmas/results/results.component';
import { SoftlayerFileListComponent } from './shared/components/softlayer-file-list/softlayer-file-list.component';
import { DashboardComponent } from './modules/dashboard/dashboard.component';
import { ReviewResultsComponent } from './modules/softlayer/review-results/review-results.component';
import { InvoiceDetailsComponent } from './modules/dashboard/invoice-details/invoice-details.component';
import { FormsModule } from '#angular/forms';
import { LowDollarNewRecordComponent } from './modules/lowDollarException/lowDollarNewRecord.component';
#NgModule({
declarations: [
AppComponent,
CmasComponent,
FinanceComponent,
ErrorComponent,
MenuComponent,
BasicComponent,
HeaderComponent,
TermsComponent,
FileListingComponent,
PreProcessedPipe,
ProcessedPipe,
ConfirmCancelComponent,
ErrorDisplayComponent,
AboutComponent,
ResultsComponent,
SoftlayerComponent,
SoftlayerFileListComponent,
DashboardComponent,
ReviewResultsComponent,
InvoiceDetailsComponent,
LowDollarExceptionComponent,
LowDollarNewRecordComponent
],
imports: [BrowserModule, HttpClientModule, AppRoutingModule, FormsModule],
providers: [
ProfileService,
FinanceService,
CmasService,
SoftlayerService,
DashboardService,
LowDollarExceptionService,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
deps: [Router],
multi: true,
},
{ provide: APP_BASE_HREF, useValue: '/sprint-cost-recovery' },
],
bootstrap: [AppComponent],
})
export class AppModule {}
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import listadeTerms from '../assets/config/properties.json';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
constructor() {}
ngOnInit() {
this.openOverlay();
}
openOverlay() {
var sheet = document.createElement('style');
sheet.innerHTML =
'.ds-full-width {visibility: hidden;} .usabilla_live_button_container{visibility: hidden;}';
document.body.appendChild(sheet);
if (document.getElementById('termsDialog')) {
var overlayElement = document.querySelector('#termsDialog');
overlayElement.classList.add('ds-open');
document
.querySelector('#termsDialogCloseBtn')
.addEventListener('click', load);
}
function load() {
var div = document.getElementById('termsDialog');
sheet.innerHTML = '.usabilla_live_button_container{visibility: true;}';
var parent = div.parentElement;
parent.removeChild(div);
var node = sheet.parentNode;
node.removeChild(sheet);
}
}
}
app-routing.module.ts
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
// Components
import { CmasComponent } from './modules/cmas/cmas.component';
import { FinanceComponent } from './modules/finance/finance.component';
import { ErrorComponent } from './modules/error/error/error.component';
import { AboutComponent } from './modules/about/about.component';
import { SoftlayerComponent } from './modules/softlayer/softlayer.component';
import { DashboardComponent } from './modules/dashboard/dashboard.component';
import { LowDollarExceptionComponent } from './modules/lowDollarException/lowDollarException.component';
import { LowDollarNewRecordComponent } from './modules/lowDollarException/lowDollarNewRecord.component';
const appRoutes: Routes = [
{ path: 'finance', component: FinanceComponent },
{ path: 'cmas-process', component: CmasComponent },
{ path: 'about', component: AboutComponent },
{ path: 'softlayer-process', component: SoftlayerComponent },
{ path: 'cost-dashboard', component: DashboardComponent },
{ path: 'low-dollar', component: LowDollarExceptionComponent },
{ path: 'low-dollar/create', component: LowDollarNewRecordComponent },
{ path: 'error/auth', component: ErrorComponent, data: { forbidden: true } },
{ path: '', redirectTo: '/finance', pathMatch: 'full' },
{
path: 'error/badgateway',
component: ErrorComponent,
data: { badgateway: true },
},
];
#NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
The way to achieve this in Angular is through the Route Guards. At a high level, it was like so:
Create the route guards. It returns a true or false depending on a condition it checks.
Add the canActivate parameter to the routes that need to be checked for authentication, e.g.:
const appRoutes: Routes = [
{ path: 'finance', component: FinanceComponent, canActivate: [AuthGuard] },
{ path: 'cmas-process', component: CmasComponent, canActivate: [AuthGuard] },
If the user is not authenticated, the redirect (to the login page for example) is specified in the route guard:
#Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivateChild {
constructor(
private authService: AuthService,
private logger: NGXLogger,
private router: Router
) {}
canActivateChild(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> {
return this.authService.isLoggedIn().pipe(
map(isLoggedIn => {
if (!isLoggedIn) {
return this.router.parseUrl('/login');
}
return true;
})
);
}
}
I am a newbie in NestJs world. As far as I know, I imported everything needed in the JwtStrategy. I don't know where it went wrong. Can somebody help me with this?
As far as I referred to documetation, Whenever we want to use any entity in a module, we should import that entity in the imports field in the #Module() decorator. I did it.
jwt.strategy.ts
import { Injectable, UnauthorizedException } from "#nestjs/common";
import { PassportStrategy } from "#nestjs/passport";
import { Strategy, ExtractJwt } from "passport-jwt";
import { InjectRepository } from "#nestjs/typeorm";
import { Repository } from "typeorm";
import { UserEntity } from "src/entities/user.entity";
import { AuthPayload } from "src/common/dtos/user.dto";
#Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
#InjectRepository(UserEntity)
private userRepo: Repository<UserEntity>
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.SECRETKEY
});
}
async validate(payload: AuthPayload): Promise<UserEntity> {
const { username } = payload;
const user = this.userRepo.findOne({ where: { username: username } });
if(!user) {
throw new UnauthorizedException();
}
return user;
}
}
auth.module.ts
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { TypeOrmModule } from '#nestjs/typeorm';
import { UserEntity } from 'src/entities/user.entity';
import { JwtModule } from '#nestjs/jwt';
import { PassportModule } from '#nestjs/passport';
import { JwtStrategy } from './jwt.strategy';
#Module({
imports: [
TypeOrmModule.forFeature([UserEntity]),
JwtModule.register({
secret: process.env.SECRETKEY,
}),
PassportModule.register({
defaultStrategy: 'jwt'
})
],
providers: [AuthService, JwtStrategy],
controllers: [AuthController],
exports: [PassportModule, JwtStrategy]
})
export class AuthModule {}
user.entity.ts
import { Entity, Column, OneToMany, JoinTable, BeforeInsert } from "typeorm";
import { AbstractEntity } from "./abstract-entity.abstract";
import { IsEmail } from "class-validator";
import { Exclude, classToPlain } from "class-transformer";
import * as bcrypt from "bcryptjs";
import { CategoryEntity } from "./category.entity";
import { ArticleEntity } from "./article.entity";
#Entity('User')
export class UserEntity extends AbstractEntity {
#Column({
type: "varchar",
length: 80
})
fullName: string;
#Column({
type: "varchar",
unique: true
})
#IsEmail()
email: string;
#Column({
type: "varchar",
unique: true
})
username: string;
#Column({
type: "varchar"
})
#Exclude()
password: string;
#Column({
default: null,
nullable: true
})
avatar: string | null;
#Column({
type: "varchar",
unique: true
})
phoneNumber: string;
#Column({
type: "boolean",
default: false
})
isAdmin: boolean;
#Column({
type: "boolean",
default: false
})
isStaff: boolean;
#Column({
type: "boolean",
default: false
})
isEmailVerified: boolean;
#OneToMany(type => CategoryEntity, category => category.createdBy)
#JoinTable()
categories: CategoryEntity[];
#OneToMany(type => ArticleEntity, article => article.createdBy)
#JoinTable()
articles: ArticleEntity[];
#BeforeInsert()
async hashPassword() {
this.password = await bcrypt.hash(this.password, 10);
}
async comparePassword(attempt: string): Promise<boolean> {
return await bcrypt.compare(attempt, this.password);
}
toJSON(): any {
return classToPlain(this);
}
}
app.module.ts
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from "#nestjs/typeorm";
import { APP_FILTER, APP_INTERCEPTOR } from '#nestjs/core';
import {
DatabaseConnectionService
} from "./utils/database-connection.service";
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';
import { ArticlesModule } from './articles/articles.module';
import { HttpExceptionFilter } from './common/exception-filters/http-exception.filter';
import { ResponseInterceptor } from './common/interceptors/response.interceptor';
import { CategoryModule } from './category/category.module';
#Module({
imports: [
TypeOrmModule.forRootAsync({
useClass: DatabaseConnectionService
}),
AuthModule,
UsersModule,
ArticlesModule,
CategoryModule,
],
controllers: [AppController],
providers: [
// {
// provide: APP_INTERCEPTOR,
// useClass: ResponseInterceptor
// },
{
provide: APP_FILTER,
useClass: HttpExceptionFilter
},
AppService
],
})
export class AppModule {}
database-connection.service.ts
import { Injectable } from "#nestjs/common";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "#nestjs/typeorm";
import { truncate } from "fs";
#Injectable()
export class DatabaseConnectionService implements TypeOrmOptionsFactory {
createTypeOrmOptions(): TypeOrmModuleOptions {
return {
type: "mysql",
host: process.env.HOST,
port: parseInt(process.env.PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DATABASE,
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
dropSchema: true,
autoLoadEntities: true,
logger: "simple-console"
};
}
}
The Error is as follows:
Based on your error, somewhere you have JwtStrategy in your imports array. If you need the JwtStrategy you should instead import the AuthModule, as providers should only be in the providers array and should never be in imports.
Consider to move to Active Record pattern. All what you need to do is just to let your AbstractEntity extends BaseEntity of TypeOrm.
You can remove all typeorm features imports like:
TypeOrmModule.forFeature([UserEntity])
and all dependency injections for repository like:
#InjectRepository(UserEntity)
private userRepo: Repository<UserEntity>
Just use the entity class for querying:
const user = await UserEntity.findOne({ where: { username } });
I am working on Angular with v 5 app. I am doing API fetching and using https://angular.io/guide/http document. But I am unable to see anything in my view.
How can I fix this problem with document provided data?
My folder structure:
https://imgur.com/A03KtDy
There isn't any bug in terminal:
https://imgur.com/a/AEKxv
No issues in console:
https://imgur.com/JaPTvXZ
File: app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { HttpClientModule } from '#angular/common/http';
import { AppComponent } from './app.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { HomeComponent } from './components/home/home.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { ConfigService } from './services/config.service';
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'dashboard', component: DashboardComponent },
];
#NgModule({
declarations: [
AppComponent,
NavbarComponent,
HomeComponent,
DashboardComponent
],
imports: [
BrowserModule,
HttpClientModule,
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
// other imports here
],
providers: [ConfigService],
bootstrap: [AppComponent]
})
export class AppModule { }
file: config.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Config } from './config';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
configUrl : 'http://localhost:3000/api/get';
getConfig() {
return this.http.get<Config>(this.configUrl)
}
}
file: dashboard.component.ts
import { Component, OnInit } from '#angular/core';
import { ConfigService } from '../../services/config.service';
import { Config } from '../../services/config';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
constructor(private configService : ConfigService) { }
ngOnInit() { }
config: Config;
showConfig() {
this.configService.getConfig()
// clone the data object, using its known Config shape
.subscribe(data => this.config = { ...data });
}
}
file: dashboard.component.html
<ul class="list-group" *ngFor="let config of configs">
<li class="list-group-item list-group-item-dark">{{config.name}}</li>
</ul>
file: config.ts
export interface Config {
name : string
}
I don't see in your code, that you call showConfig() method.
Maybe you forget to add call to ngOnInit() method?
ngOnInit() {
this.showConfig();
}