How should nestjs-redis be used correctly? Any example of nestjs-redis? - redis

When I used nestjs-redis recently, there is no official example, I don't know how to use it correctly.
app.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { typeOrmConfig } from './config/typeorm.config';
import { AuthModule } from './base/auth.module';
import { RedisModule } from 'nestjs-redis';
import { SmsService } from './common/providers/sms.service';
import { redisConfig } from './config/redis.config';
import { RedisClientService } from './common/providers/redis-client.service';
#Module({
imports: [
TypeOrmModule.forRoot(typeOrmConfig),
AuthModule,
RedisModule.register(redisConfig),
],
providers: [SmsService, RedisClientService],
})
export class AppModule {}
redis-client.service.ts
import { Injectable } from '#nestjs/common';
import { RedisService } from 'nestjs-redis';
import * as Redis from 'ioredis';
#Injectable()
export class RedisClientService {
// I want to add a private variable.
private _client
constructor(
private readonly redisService: RedisService,
) {
this.getClient().then((client) => (this._client = client));
}
async getClient(): Promise<Redis.Redis> {
const client = await this.redisService.getClient('main');
return client;
}
async setValue(key: string, value: string, expiryMode: string|any, time: string|any) : Promise<boolean>{
// use _client in this method
// this._client.set() // this is correct?
const client = await this.getClient();
const result = await client.set(key, value, expiryMode, time);
return result == 'OK';
}
}
My example above declares a variable _client, but I don’t know how to use it right?

Here's my resolution:
import { Injectable } from '#nestjs/common';
import { RedisService } from 'nestjs-redis';
import * as Redis from 'ioredis';
#Injectable()
export class RedisClientService {
private _client: Redis.Redis;
constructor(private readonly redisService: RedisService) {
this._client = this.redisService.getClient('main');
}
async getClient(): Promise<Redis.Redis> {
const client = this.redisService.getClient('main');
return client;
}
async setValue(
key: string,
value: string,
expiryMode?: string | any[],
time?: number | string,
): Promise<boolean> {
const result = await this._client.set(key, value, expiryMode, time);
return result == 'OK';
}
async getValue(key: string): Promise<string> {
const result = await this._client.get(key);
return result;
}
}
create a private variable _client in the class.
in constructor initial the value.
use it in the methods: getValue and setValue
perfect.

Related

NestJS Authentication - Passport strategy, JWT creation problem

I'm following the official NestJS documentation. Currently, I'm trying to implement the authentication step with Passport strategy. I did every step, as the documentation says, but I got stuck where I need to generate the JWT with the jwtService.sign() method.
The error, that I'm getting is:
ERROR [ExceptionsHandler] secretOrPrivateKey must have a value`.
Here are the code snippets:
AuthModule:
#Module({
imports: [
UserModule,
PassportModule,
User,
TypeOrmModule.forFeature([User]),
JwtModule.register({
secret: 'somerandomsecret',
signOptions: { expiresIn: '60s' }
})
],
providers: [AuthService, LocalStrategy, UserService],
exports: [AuthService]
})
export class AuthModule {}
AuthService
#Injectable()
export class AuthService {
constructor(
private userService: UserService,
private jwtService: JwtService
){}
async validateUser(email: string, pass: string): Promise<any> {
const user = await this.userService.findByEmail(email);
const isMatch = await comparePasswords(pass, user.password);
if( user && isMatch) {
const { password, ...result } = user;
return result;
}
return null;
}
async signIn(user: any) {
const payload = { username: user.email, sub: user.id };
return this.jwtService.sign(payload)
}
}
And inside the User controller, I'm calling the method signIn from the AuthService.
UserController
import {
Body,
Controller,
Post,
HttpException,
HttpStatus,
Request,
UseGuards,
Bind,
} from "#nestjs/common";
import { UserService } from "./user.service";
import { SignUpDataValidation } from "./user.validation";
import { hashPassword } from "../../utils/hash-password";
import { AuthGuard } from '#nestjs/passport';
import { AuthService } from '../auth/auth.servers';
import { LocalAuthGuard } from '../auth/local-auth.guard';
#Controller("user")
export class UserController {
constructor(
private userService: UserService,
private authService: AuthService
) {}
#UseGuards(LocalAuthGuard)
#Post("/signin")
#Bind(Request())
async signIn(req) {
return this.authService.signIn(req.user)
}
}
UserModule
import { Module } from "#nestjs/common";
import { UserController } from "./user.controller";
import { UserService } from "./user.service";
import { TypeOrmModule } from "#nestjs/typeorm";
import { User } from "src/modules/user/user.entity";
import { AuthService } from '../auth/auth.servers';
import { JwtService } from '#nestjs/jwt';
#Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [UserService, AuthService, JwtService],
})
export class UserModule {}
LocalStrategy
import { Injectable, UnauthorizedException } from '#nestjs/common';
import { PassportStrategy } from '#nestjs/passport';
import { Strategy } from 'passport-local';
import { AuthService } from './auth.servers';
#Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({usernameField: 'email'});
}
async validate(email: string, password: string): Promise<any> {
const user = await this.authService.validateUser(email,
password);
if(!user) {
throw new UnauthorizedException()
}
return user;
}
}
As you can see, I'm also using Guards, but I'm not going to send you that code to avoid confusion.
So, can anybody tell me, why I'm getting this ERROR? Am I missing something?
Here is the link to the particular NestJS documentation page with a feature that I'm trying to implement: https://docs.nestjs.com/security/authentication

Dependencies not being injected on NestJS with Serverless and AWS

Everyone,
I'm trying to setup my first NestJS application. It is backed by Serverless on AWS.
I created a simple Controller that has a Service as a dependency. When I hit the endpoint with my HTTP Client, the object that should contain the Service instance is undefined. I'm not able to make it work. Could you help?
handler.ts
import { Context, Handler } from 'aws-lambda';
import { NestFactory } from '#nestjs/core';
import { AppModule } from './src/module';
import { Server } from 'http';
import { ExpressAdapter } from '#nestjs/platform-express';
import * as serverless from 'aws-serverless-express';
import * as express from 'express';
import {DB} from './src/libs/db';
let cachedServer: Server;
function bootstrapServer(): Promise<Server> {
const expressApp = express();
const adapter = new ExpressAdapter(expressApp);
return NestFactory.create(AppModule, adapter)
.then(app => app.enableCors())
.then(app => app.init())
.then(() => DB.connect())
.then(() => serverless.createServer(expressApp));
}
export const handle: Handler = (event: any, context: Context) => {
if (!cachedServer) {
bootstrapServer().then(server => {
cachedServer = server;
return serverless.proxy(server, event, context);
});
} else {
return serverless.proxy(cachedServer, event, context);
}
};
module.ts
import { Module } from '#nestjs/common';
import { EventController } from './event.controller';
import { EventService } from './event.service';
#Module({
controllers: [EventController],
providers: [EventService],
})
export class AppModule {}
event.service.ts
import { Injectable } from '#nestjs/common';
interface Event{}
#Injectable()
export class EventService {
create(event: Event) {
return {
id: Date.now()
}
}
}
event.controller.ts
import { Controller, Post, Body } from '#nestjs/common';
import { EventService } from './event.service';
interface Event { }
#Controller('event')
export class EventController {
constructor(private readonly eventService: EventService) { }
#Post()
async create(#Body() req)
{
this.eventService.create(req);
}
}
So this.eventService is always undefined. What is wrong with this implementation?
Maybe you are missing a line from tsconfig add this below:
"emitDecoratorMetadata": true
Credits to the God of Nestjs Mr. Kamil's reply:
https://stackoverflow.com/a/50121886/6301493

How to dynamically create a component on ngOnInit()?

How can you dynamically create a component on ngOnInit()?
I'm getting an error of "Cannot read property 'clear' of undefined" when I'm creating the component on the ngOnInit.
Here is my component:
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver, ComponentRef, ComponentFactory } from '#angular/core';
import { SpinnerService } from '../../tools/spinner/spinner.service';
import { CardService } from './card.service';
import { CardDatagridComponent } from './card-datagrid/card-datagrid.component';
#Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss']
})
export class CardComponent implements OnInit {
#ViewChild("cardDataGridContainer", { read: ViewContainerRef }) container;
public renderReady: boolean = false;
public componentRef: ComponentRef<any>;
public selectedStatus = 'A';
constructor(private spinner: SpinnerService, private cardService: CardService, private resolver: ComponentFactoryResolver) { }
ngOnInit() {
this.spinner.show();
setTimeout(() => {
this.spinner.hide();
this.renderReady = true;
}, 2000);
this.selectTabStatus(this.selectedStatus);
}
selectTabStatus(status) {
this.selectedStatus = status;
this.createComponent(status);
}
createComponent(status) {
this.container.clear();
const factory: ComponentFactory<any> = this.resolver.resolveComponentFactory(CardDatagridComponent)
this.componentRef = this.container.createComponent(factory);
this.componentRef.instance.cardStatus = status;
}
ngOnDestroy() {
this.componentRef.destroy();
}
}
Any suggestion guys? Thanks!
AngularJS !== Angular, you should remove the tag. And perhaps add "Typescript"
anyway here I accomplished to do what you're looking for
Blitz
In Angular4+ Renderer2 was added so:
import {Renderer2, ElementRef} from "#angular/core";
constructor(private targetEl: ElementRef, private renderer: Renderer2) {
this.$matCard = this.renderer.createElement('mat-card');
const matCardInner = this.renderer.createText('Dynamic card!');
this.renderer.appendChild(this.$matCard, matCardInner);
const container = this.targetEl.nativeElement;
this.renderer.appendChild(container, this.$matCard);
}

Angular 5: Solving unresolved dependency in constructor

I'm trying to create a generic HttpService for my Angular 5 project.
The error I am getting:
Uncaught Error: Can't resolve all parameters for HttpService: ([object Object], [object Object], [object Object], ?)
app/util/constants.ts
import { Injectable } from "#angular/core";
#Injectable()
export class SERVER {
readonly ROOT:string = 'http://localhost:8888/';
readonly API_PATH:string = 'api/v1/';
}
#Injectable()
export class API_URLS {
readonly USER:string = 'user/';
}
app/serializers/serializer.ts
import { Resource } from 'app/models/resource';
export interface Serializer {
fromJson(json: any): Resource;
toJson(resource: Resource): any;
}
app/models/resource.ts
export class Resource {
id: number;
}
app/models/user.model.ts
import { Resource } from 'app/models/resource';
export class User extends Resource{
id: number;
name: string;
email: string;
gender: string;
address: string;
landmark: string;
client_id: number;
dealer_id: number;
phone_number: string;
alternate_phone_number: string;
status: string;
is_active: boolean;
date_created: string;
date_updated: string;
}
app/serializers/user.serializer.ts
import { User } from 'app/models/user.model';
import { Serializer } from 'app/serializers/serializer';
export class UserSerializer implements Serializer {
fromJson(json: any): User {
const user = new User();
user.id = json.id;
user.client_id = json.client_id;
user.dealer_id = json.dealer_id;
user.status = json.status;
user.is_active = json.is_active;
user.date_created = json.date_created;
user.date_updated = json.date_updated;
return user;
}
toJson(user: User): any {
return {
id: user.id,
client_id: user.client_id,
dealer_id: user.dealer_id,
status: user.status,
is_active: user.is_active,
date_created: user.date_created,
date_updated: user.date_updated,
};
}
}
app/services/user.service.ts
import { Injectable } from '#angular/core';
import { SERVER } from 'app/util/constants';
import { API_URLS } from 'app/util/constants';
import { User } from 'app/models/user.model';
import { HttpClient } from '#angular/common/http';
import { HttpService } from 'app/services/http.service';
import { UserSerializer } from 'app/serializers/user.serializer';
#Injectable()
export class UserService extends HttpService<User> {
constructor(
server: SERVER,
API_URLS: API_URLS,
httpClient: HttpClient
) {
super(
server,
httpClient,
API_URLS.USER,
new UserSerializer());
}
}
app/app.module.ts
import { Observable } from 'rxjs/Rx';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { CommonModule } from '#angular/common';
import { RouterModule } from '#angular/router';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '#angular/common/http';
import { BrowserModule } from '#angular/platform-browser';
/************** Services *****************/
import { UserService } from './services/user.service';
/************** Components *****************/
import { UserComponent } from './components/user/user.component';
/************** Constant *****************/
import { SERVER } from './util/constants';
import { API_URLS } from './util/constants';
import { OPERATION_TYPES } from './util/constants';
import { REQUEST_METHODS } from './util/constants';
import { Resource } from './models/resource';
#NgModule({
declarations: [
AppComponent,
UserComponent,
],
imports: [
CommonModule,
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [
SERVER,
API_URLS,
OPERATION_TYPES,
REQUEST_METHODS,
Resource,
UserService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Edit: Added missing code
app/services/http.service.ts
import { Observable } from 'rxjs/Rx';
import { Resource } from 'app/models/resource';
import { Serializer } from 'app/serializers/serializer';
import { SERVER } from 'app/util/constants';
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class HttpService<T extends Resource> {
constructor(
private SERVER: SERVER,
private httpClient: HttpClient,
private API_URL: string,
private serializer: Serializer) { }
/*
* Get single record by id
*/
read(id: number): Observable<T> {
return this.httpClient.get<T>(`${this.SERVER.ROOT}/${this.SERVER.API_PATH}/${this.API_URL}/${id}`).map(data => this.serializer.fromJson(data) as T);
}
/*
* Get all records by page
*/
readRecords(): Observable<T[]>{
return this.httpClient.get<T[]>(`${this.SERVER.ROOT}/${this.SERVER.API_PATH}/${this.API_URL}`).map((data: any) => this.convertData(data.items) as T[]);
}
/*
* Create new record
*/
create(record: T): Observable<T>{
return this.httpClient.post<T>(`${this.SERVER.ROOT}/${this.SERVER.API_PATH}/${this.API_URL}`, record).map(data => this.serializer.fromJson(data) as T);
}
/*
* Update record
*/
update(record: T): Observable<T>{
return this.httpClient.put<T>(`${this.SERVER.ROOT}/${this.SERVER.API_PATH}/${this.API_URL}/${record.id}`, record).map(data => this.serializer.fromJson(data) as T);
}
/*
* Remove record
*/
remove(id: number) {
return this.httpClient.delete(`${this.SERVER.ROOT}/${this.SERVER.API_PATH}/${this.API_URL}/${id}`);
}
private convertData(data: any): T[] {
return data.map(item => this.serializer.fromJson(item));
}
}
What am I missing?
I solved this by making the Serializer abstract class and making serializers injectable.
import { Injectable } from '#angular/core';
import { Resource } from 'app/models/resource';
#Injectable()
export abstract class Serializer {
abstract fromJson(json: any): Resource;
abstract toJson(resource: Resource): any;
}
And
import { Injectable } from '#angular/core';
import { User } from 'app/models/user.model';
import { Serializer } from 'app/serializers/serializer';
#Injectable()
export class UserSerializer implements Serializer {
fromJson(json: any): User {
const user = new User();
user.id = json.id;
user.client_id = json.client_id;
user.dealer_id = json.dealer_id;
user.status = json.status;
user.is_active = json.is_active;
user.date_created = json.date_created;
user.date_updated = json.date_updated;
return user;
}
toJson(user: User): any {
return {
id: user.id,
client_id: user.client_id,
dealer_id: user.dealer_id,
status: user.status,
is_active: user.is_active,
date_created: user.date_created,
date_updated: user.date_updated,
};
}
}

Angular2 Service Unit Test Fails with TypeError: undefined is not an object

I am testing my authService. This is the full Test, yet Karma tells me, authService is undefined. I have plenty of Service which AuthService depends upon, but I provided and injected them all properly.
Error: Cannot resolve all parameters for 'AuthService'(BackendService, Store, LoggerService, undefined, ErrorService). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthService' is decorated with Injectable. in /var/folders/zb/tpysrhsx7hbg1dnsn4gwtqq00000gn/T/8715f9a6c29e748f52c8f59e3e1daae3.browserify (line 34976)
authservice.spec.ts
import { provide } from "#angular/core";
import { AuthHttp } from "angular2-jwt";
import { HTTP_PROVIDERS, XHRBackend } from "#angular/http";
import { MockBackend } from "#angular/http/testing";
import {
TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS
} from "#angular/platform-browser-dynamic/testing";
import {
beforeEachProviders,
inject,
beforeEach,
it,
describe,
setBaseTestProviders
} from "#angular/core/testing";
import { Subject } from "rxjs/Subject";
import { AuthService } from "./auth.service";
import { BackendService } from "../../backend/backend.service";
import { ErrorService } from "../../error/error.service";
import { LoggerService } from "../../logger/logger.service";
import { NavService } from "../../nav/nav-service/nav.service";
import { Store } from "#ngrx/store";
import { TestComponentBuilder } from "#angular/compiler/testing";
import { ToastController, AlertController } from "ionic-angular";
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
describe("AuthService", () => {
let response = new Subject();
let tcb;
let authService;
let navService;
let backendService;
let errorService;
let store;
let loggerService;
class StubErrorService extends ErrorService {
constructor() {
super(null, null);
}
toast(title) {
console.error(title);
}
modal(title, subtitle) {
console.error(title, subtitle);
}
}
class StubBackendService extends BackendService {
}
class StubStore extends Store<any> {
}
class StubLoggerService extends LoggerService {
}
class StubNavService extends NavService {
}
// PROVIDE
beforeEachProviders(() => [
HTTP_PROVIDERS,
provide(AuthHttp, {
useValue: {
get: (url: string) => {
return response;
}
}
}),
AuthService,
TestComponentBuilder,
provide(ToastController, {useClass: null}),
provide(AlertController, {useClass: null}),
provide(ErrorService, {useClass: StubErrorService}),
provide(XHRBackend, {useClass: MockBackend}),
provide(BackendService, {useClass: StubBackendService}),
provide(Store, {useClass: StubStore}),
provide(LoggerService, {useClass: StubLoggerService}),
provide(NavService, {useClass: StubNavService})
]);
// INJECTS
beforeEach(inject([TestComponentBuilder, AuthService, ErrorService, BackendService, Store, LoggerService, NavService], (_tcb, as, es, bs, s, ls, ns) => {
tcb = _tcb;
authService = as;
navService = ns;
errorService = es;
store = s;
backendService = bs;
loggerService = ls;
}));
it("should test authservice", () => {
authService.logout();
});
});
I don't know if its relevant anymore, just to say I had an almost identical issue and I resolved it following the official docs on how to test services. Hope it helps!