This is what my auth.module.ts looks like:
import { Module } from "#nestjs/common";
import { ConfigModule, ConfigService } from "#nestjs/config";
import { JwtModule } from "#nestjs/jwt";
import { PassportModule } from "#nestjs/passport";
import { TypeOrmModule } from "#nestjs/typeorm";
import appConfig from "src/config/app.config";
import devConfig from "src/config/dev.config";
import stagConfig from "src/config/stag.config";
import { User } from "src/entities/entity/user.entity";
import { AuthService } from "./auth.service";
import { JwtStrategy } from "./passport-strategies/jwt-strategy";
import { LocalStrategy } from "./passport-strategies/local-strategy";
#Module({
imports: [
PassportModule,
ConfigModule.forRoot({
load: [appConfig, devConfig, stagConfig],
ignoreEnvFile: true,
isGlobal: true,
}),
TypeOrmModule.forFeature([
User
]),
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
// secret: configService.get<string>('jwt.secret'),
secret: process.env.TOKEN_KEY,
signOptions: { expiresIn: 30 }
}),
inject: [ConfigService]
}),
],
providers: [
AuthService,
LocalStrategy,
JwtStrategy
],
exports: [AuthService],
})
export class AuthModule {}
As you can see I have set signOptions: { expiresIn: 30 } but when I analyze the token it has no expiration parameter and does not expire.
I am using https://jwt.io/#encoded-jwt to analyze the token:
You have to pass the expiresIn value as string and mention s for seconds like this
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
Do let me know if this works!
The same problem. search ignoreExpiration flag. Here's my problem
e:
#Injectable()
export class JWTStrategy extends PassportStrategy(Strategy) {
constructor(
readonly configService: ConfigService,
private userService: UserService,
) {
super({
jwtFromRequest: ExtractJwt.fromHeader(
configService.get('API_ACCESS_TOKEN_HEADER'),
),
ignoreExpiration: true, // *** FIXME: here
secretOrKey: configService.get('API_ACCESS_TOKEN_SECRET'),
});
}
...
Here is type:
export interface StrategyOptions {
secretOrKey?: string | Buffer | undefined;
secretOrKeyProvider?: SecretOrKeyProvider | undefined;
jwtFromRequest: JwtFromRequestFunction;
issuer?: string | undefined;
audience?: string | undefined;
algorithms?: string[] | undefined;
ignoreExpiration?: boolean | undefined;
passReqToCallback?: boolean | undefined;
jsonWebTokenOptions?: VerifyOptions | undefined;
}
The ignoreExpiration used, https://github.com/auth0/node-jsonwebtoken/blob/master/verify.js#L147
Hope it will help you
Related
I am working on a small api using nestjs and passeport js
I have been trying to access the content of my env file, from within my auth module...but it's surpinsigly challenging...
import { userService } from 'src/user/services/user.service';
import { AuthService } from './auth.service';
import { PassportModule } from '#nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { JwtModule } from '#nestjs/jwt';
import { JwtStrategy } from './jwt.strategy';
import { ConfigService } from '#nestjs/config';
#Module({
providers: [AuthService, userService, LocalStrategy, JwtStrategy],
imports: [
TypeOrmModule.forFeature([UserEntity, SpotEntity, SpotUserEntity]),
UserModule,
PassportModule,
JwtModule.register({
secret: ConfigService.get('JWT_SECRET'),
signOptions: { expiresIn: '600s' },
}),
],
exports: [AuthService],
})
export class AuthModule {}
Off course this cannot work because i am trying to utilize ConfigService.get() instead of this.configService.get()
I know i would need to instanciate configService in a constructor first, but modules do not have constructors, this is where i'm stuck at.
You can try registerAsync i.e
import { ConfigModule, ConfigService } from '#nestjs/config';
......
imports: [
PassportModule.register({
defaultStrategy: 'jwt',
}),
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => {
return {
signOptions: {
expiresIn: config.get<string>('JWT_EXPIRY'),
},
secret: config.get<string>('JWT_SECRET'),
};
},
inject: [ConfigService],
})
]
....
im getting this error Cannot return null for non-nullable field CityBoundaries.city_name. from mongoDB, but if im using static json data, i get my response fine. Here's my code. Any help will be appreciated :)
city-boundries.model.ts
import { ObjectType, Field, ID, Int, Float } from '#nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
import 'dotenv/config';
import { CityBoundiresFeatures } from 'src/types/city-boundries-features';
import mongoose from 'mongoose';
export type CityBoundriesDocument = CityBoundaries & Document;
#Schema()
#ObjectType()
export class CityBoundaries extends Document {
#Field(() => ID, { nullable: true })
_id: string | number;
#Prop()
#Field()
readonly city_admin_level: number;
#Prop({ required: true })
#Field()
readonly city_name: string;
#Prop({ required: true })
#Field(() => Float)
readonly city_id: number;
#Prop({ required: true })
#Field(() => Float)
readonly city_osm_id: number;
#Prop({
required: true,
type: mongoose.Schema.Types.ObjectId,
ref: 'CityBoundiresFeatures',
})
#Field(() => [CityBoundiresFeatures], { nullable: true })
features: CityBoundiresFeatures[];
#Prop({ required: true })
#Field({ nullable: true })
type: string;
}
export const CityBoundriesSchema = SchemaFactory.createForClass(CityBoundaries);
city-boundries.module.ts
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import {
CityBoundaries,
CityBoundriesSchema,
} from 'src/models/city-boundries.model';
import { CityBoundriesService } from 'src/services/city-boundries.service';
import { CityBoundriesResolvers } from 'src/resolvers/city-boundries.resolver';
import { Bop500_City, CitiesSchema } from 'src/models/cities.model';
import { CitiesService } from 'src/services/cities.service';
#Module({
imports: [
MongooseModule.forFeature([
{
name: CityBoundaries.name,
schema: CityBoundriesSchema,
},
{ name: Bop500_City.name, schema: CitiesSchema },
]),
],
providers: [CityBoundriesService, CityBoundriesResolvers, CitiesService],
})
export class CityBoundriesModule {}
cities.resolver.ts
import { Resolver, Query, Args, ResolveField, Parent } from '#nestjs/graphql';
import { Bop500_City } from 'src/models/cities.model';
import { CityBoundaries } from 'src/models/city-boundries.model';
import { CitiesService } from 'src/services/cities.service';
import { CityBoundriesService } from 'src/services/city-boundries.service';
#Resolver(() => Bop500_City)
export class CitiesResolvers {
constructor(
private readonly citiesService: CitiesService,
private readonly cityBoundariesService: CityBoundriesService,
) {}
#Query(() => [Bop500_City])
/**
* #returns list of all cities
*/
async getAllCities() {
return this.citiesService.findMany();
}
#Query(() => [Bop500_City], { nullable: true })
/**
* #param {string} value take city name as argument from user
* #returns detail of city
*/
async getCity(#Args('city') value: string) {
const res = await this.citiesService.findOneByName(value);
console.log('Response: ', res);
return res;
}
#ResolveField(() => CityBoundaries)
async getBoundries(#Parent() parent: Bop500_City) {
const res = await this.cityBoundariesService.findOneByCityName(
parent.city_name,
);
console.log('Response: ', res);
return res;
}
}
city-boundries.service.ts
import { Injectable } from '#nestjs/common';
import { Model } from 'mongoose';
import { InjectModel } from '#nestjs/mongoose';
import {
CityBoundaries,
CityBoundriesDocument,
} from 'src/models/city-boundries.model';
import * as cityBoundriesData from '../static/City_boundaries.json';
#Injectable()
export class CityBoundriesService {
constructor(
#InjectModel(CityBoundaries.name)
private cityBoundriesModel: Model<CityBoundriesDocument>,
) {}
/**
* #param {string} cityName take city name as argument from user
* #returns boundries of city
*/
async findOneByCityName(cityName: string) {
const res = await this.cityBoundriesModel.find({ city_name: cityName });
return res;
}
}
app.module.ts
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '#nestjs/apollo';
import { MongooseModule } from '#nestjs/mongoose';
import { CitiesModule } from './module/cities.module';
import 'dotenv/config';
import { CityBoundriesModule } from './module/city-boundries.module';
#Module({
imports: [
MongooseModule.forRoot(process.env.MONGODB_DB_URI, {
dbName: process.env.DB_NAME,
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: 'src/schema/schema.gql',
introspection: true,
playground: true,
}),
CitiesModule,
CityBoundriesModule,
],
})
export class AppModule {}
Errors
Error during migration generation:
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-data-api", "aurora-data-api-pg", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs".
at MissingDriverError.TypeORMError [as constructor] (D:\Projects\Mark1\api2\src\error\TypeORMError.ts:7:9)
at new MissingDriverError (D:\Projects\Mark1\api2\src\error\MissingDriverError.ts:8:9)
at DriverFactory.create (D:\Projects\Mark1\api2\src\driver\DriverFactory.ts:70:23)
at new Connection (D:\Projects\Mark1\api2\src\connection\Connection.ts:122:43)
at ConnectionManager.create (D:\Projects\Mark1\api2\src\connection\ConnectionManager.ts:61:28)
at D:\Projects\Mark1\api2\src\globals.ts:77:35
at step (D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:143:27)
at Object.next (D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:124:57)
at D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:117:75
at new Promise ()
ormConfig.ts
import { TypeOrmModuleOptions } from '#nestjs/typeorm';
import { join } from 'path';
require('dotenv').config();
class ConfigService {
constructor(private env: { [k: string]: string | undefined }) { }
private getValue(key: string, throwOnMissing = true): string {
const value = this.env[key];
if (!value && throwOnMissing) {
throw new Error(`config error - missing env.${key}`);
}
return value;
}
public ensureValues(keys: string[]) {
keys.forEach(k => this.getValue(k, true));
return this;
}
public getPort() {
return this.getValue('PORT', true);
}
public isProduction() {
const mode = this.getValue('MODE', false);
return mode != 'DEV';
}
public getTypeOrmConfig(): TypeOrmModuleOptions {
return {
type: 'postgres',
host: this.getValue('POSTGRES_HOST'),
port: parseInt(this.getValue('POSTGRES_PORT')),
username: this.getValue('POSTGRES_USER'),
password: this.getValue('POSTGRES_PASSWORD'),
database: this.getValue('POSTGRES_DATABASE'),
entities: [join(__dirname, '**', '*.entity.{ts,js}')],
migrationsTableName: 'migration',
migrations: ['src/migration/*.ts'],
cli: {
migrationsDir: 'src/migration',
},
};
}
}
const configService = new ConfigService(process.env)
.ensureValues([
'POSTGRES_HOST',
'POSTGRES_PORT',
'POSTGRES_USER',
'POSTGRES_PASSWORD',
'POSTGRES_DATABASE'
]);
export = configService ;
appmodule.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import configService from 'ormConfig';
import { AppController } from './app.controller';
import { AppService } from './app.service';
#Module({
imports: [TypeOrmModule.forRoot(configService.getTypeOrmConfig())],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
}
.env file
POSTGRES_HOST=localhost
POSTGRES_PORT=8080
POSTGRES_USER=postgres
POSTGRES_PASSWORD=saad2113
POSTGRES_DATABASE=mark1
PORT=3000
MODE=DEV
RUN_MIGRATIONS=true
I'm having a problem with Nest Js and mongoose, Im trying to make a seed for my database,
And the main problem I'm having is I cannot import service from my module, into other module.
And it constantly gives me error:
Nest can't resolve dependencies of the CategoryModel (?). Please make sure that the argument at index [0] is available in the MongooseModule context.
the main thing I'm trying to do is to create seed for my categories.
Here is my Category Module:
import { Module } from '#nestjs/common';
import { CategoryController } from './category.controller';
import { CategoryService } from './category.service';
import { MongooseModule } from '#nestjs/mongoose';
import { CategorySchema } from 'src/models/category.schema';
#Module({
imports: [MongooseModule.forFeature([{ name: 'Category', schema: CategorySchema }])],
controllers: [CategoryController],
providers: [CategoryService]
})
export class CategoryModule {}
My Category service:
import { Model } from 'mongoose';
import { Injectable, Inject } from '#nestjs/common';
import { CategoryInterface } from '../interfaces/category.interface';
import { InjectModel } from '#nestjs/mongoose';
#Injectable()
export class CategoryService {
constructor(#InjectModel('Category') private categoryModel: Model<CategoryInterface>) {}
async create(category){
const createdQuestion = new this.categoryModel(category);
return createdQuestion.save();
}
async getMainCategories() {
return this.categoryModel.find( { parent: null } );
}
}
My Category Controller:
import { Controller, Post, Get, Body, HttpCode } from '#nestjs/common';
import { CategoryService } from './category.service';
#Controller('category')
export class CategoryController {
constructor(private categoryService: CategoryService) { }
#Post()
#HttpCode(204)
async createCategory(#Body() category) {
console.log('evo je kategorija ', category);
const data = await this.categoryService.create(category);
}
#Get('/main')
async getAllCategories() {
const data = await this.categoryService.getMainCategories();
return data;
}
}
My Seeder module where I'm having provider that seed database:
import { Module } from '#nestjs/common';
import { Seeder } from './seeder';
#Module({
providers: [Seeder],
})
export class SeederModule {}
and my seeder.ts
import { Injectable } from '#nestjs/common';
import { CategoryService } from 'src/category/category.service';
#Injectable()
export class Seeder {
constructor(private categoryService: CategoryService) { }
async seed() {
}
async categories() {
// const data = await this.categoryService.createMultiple(categories);
}
}
My App.module
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CategoryModule } from './category/category.module';
import { QuizModule } from './quiz/quiz.module';
import { ConfigModule } from '#nestjs/config';
import config from './config/config';
#Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017'),
ConfigModule.forRoot({ load: [config], isGlobal: true }),
CategoryModule,
QuizModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Category Model:
import * as mongoose from 'mongoose';
export const CategorySchema = new mongoose.Schema({
name: { type:String, required:true, unique: true },
slug: { type:String, required:true, unique: true },
});
And for some reason it is not working, even If I import whole
GitHub Repository of Project: https://github.com/HunterJS-bit/react-quiz-app
CategoryModule, or CategoryService into Seeder.module ??
Note: To reproduce error try running npm run seed from
server/package.json
Thanks for the help :)
You need to have the CategoryModule add exports: [CategoryService] to allow for other modules to import the module and make use to the CategoryService. This is how you share providers in NestJS. The, you need to add imports: [CategoryModule] to the SeederModule to allow the providers of the SeederModule to use the exports of the CategoryModule. Then, everything should load up just fine.
I have this ionic 4 project (Using REST API) and have also install ionic native storage. I might have multiple questions concerning this project, but the first is:
I want to store login data so I can be able to pass a token to the header to be used for other endpoints. But if I run the app and try to login, I get the following error:
Error storing item
Object { code: 5, source: "Native", exception: null, stack: "" }
My auth ts is where my login function is:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { tap } from 'rxjs/operators';
import { ApiService } from './api.service';
import { User } from '../models/user';
import { NativeStorage } from '#ionic-native/native-storage/ngx';
#Injectable({
providedIn: 'root'
})
export class AuthService {
isLoggedIn = false;
token: any;
constructor(
private http: HttpClient,
private api: ApiService,
private storage: NativeStorage
) { }
login(account_number: Number, password: String) {
return this.http.post(this.api.API_URL + '/login',
{account_number: account_number, password: password}
).pipe(
tap(token => {
this.storage.setItem('token', token)
.then(
() => {
console.log('Token Stored', token);
},
error => console.error('Error storing item', error)
);
this.token = token;
this.isLoggedIn = true;
return token;
}),
);
}
register(name: String, email: String, phone: Number, reference: String, account_number: String, password: String) {
return this.http.post(this.api.API_URL + '/register',
{ name: name, email: email, phone: phone, reference: reference, account_number: account_number, password: password }
)
}
logout() {
const headers = new HttpHeaders({
'Authorization': "auth-token" + this.token
});
return this.http.get(this.api.API_URL + '/logout', { headers: headers })
.pipe(
tap(data => {
this.storage.remove("token");
this.isLoggedIn = false;
delete this.token;
return data;
})
)
}
getToken() {
return this.storage.getItem('token').then(
data => {
this.token = data;
if (this.token != null) {
this.isLoggedIn = true;
} else {
this.isLoggedIn = false;
}
},
error => {
this.token = null;
this.isLoggedIn = false;
}
);
}
}
And here is is my login.ts.
import { Component, OnInit } from '#angular/core';
import { ModalController, NavController } from '#ionic/angular';
import { AuthService } from 'src/app/services/auth.service';
import { AlertService } from 'src/app/services/alert.service';
import { RegisterPage } from '../register/register.page';
import { NgForm } from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
userdata: any;
constructor(
private modalC: ModalController,
private authService: AuthService,
private navCtrl: NavController,
private alertService: AlertService,
// private router: Router
) { }
ngOnInit() {
}
// Dismiss Login Modal
dismissLogin() {
this.modalC.dismiss();
}
// On Register button tap, dismiss login modal and open register modal
async registerModal() {
this.dismissLogin();
const registerModal = await this.modalC.create({
component: RegisterPage
});
return await registerModal.present();
}
login(form: NgForm) {
this.authService.login(form.value.account_number, form.value.password).subscribe(
data => {
this.userdata = data;
this.alertService.presentToast("Logged In");
console.log('this is loggin in userdata', data, "and this is the stored auth-token", this.userdata.message);
},
error => {
console.log(error, "logged in");
},
() => {
this.dismissLogin();
this.navCtrl.navigateRoot('/dashboard');
console.log('this is this.userdata', )
}
);
}
}
Here is aslo my app.module.ts
import { NgModule, ErrorHandler } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { IonicModule, IonicRouteStrategy, } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '#angular/common/http';
import { NativeStorage } from '#ionic-native/native-storage/ngx';
#NgModule({
declarations: [
AppComponent,],
entryComponents: [
],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
HttpClientModule
],
providers: [
StatusBar,
SplashScreen,
NativeStorage,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
You can simply use javascript local storage and also use Ionic native storge for your purpose.
Mostly is used localStorage.set(). In case just want to store strings.
u also use Ionic native storage for the object and many things.
https://ionicframework.com/docs/native/native-storage