I have a user collection in the database and i want to retrive a user with specific username
I have written this method but this is returning all users
findByUsername(username: string) {
return this.userModel.find({
'username' : username})
}
Why is this query not working
Controller
#Get('find/:username')
getUserById(#Param("username") username : string) : any {
console.log(username);
return this.usersService.findByUsername(username);
}
This is my user entity
import { Schema, SchemaFactory } from "#nestjs/mongoose";
import { ApiProperty } from "#nestjs/swagger";
export type UserDocument = User & Document;
#Schema()
export class User {
#ApiProperty()
id: string;
#ApiProperty()
username: string;
#ApiProperty()
email : string
#ApiProperty()
password: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
This is the service
import { Injectable } from "#nestjs/common";
import { InjectModel } from "#nestjs/mongoose";
import { Model } from "mongoose";
import { use } from "passport";
import {User,UserDocument} from '../users/entities/user.entity'
// This should be a real class/interface representing a user entity
#Injectable()
export class UsersService {
constructor(
#InjectModel(User.name) private readonly userModel : Model<User> )
{}
findById(userId: string) {
}
findByUsername(username: string) {
return this.userModel.find({"username": username}).exec();
}
Try this:
findByUsername(username: string) {
return this.userModel.find({username: username}).exec();
}
or simplified version:
findByUsername(username: string) {
return this.userModel.find({username}).exec();
}
Briefly, the cause is the 'username' field typed with quotes and missing .exec() method at the end of the chain.
Also, schema should be prepared for Mongoose by decorating fields with the #Prop() decorator:
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
#Schema()
export class User {
#ApiProperty()
#Prop()
id: string;
#ApiProperty()
#Prop()
username: string;
#ApiProperty()
#Prop()
email : string
#ApiProperty()
#Prop()
password: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
You can use the findOne method in Mongoose:
findByUsername(username: string) {
return this.userModel.findOne({ username })
}
Related
I have a user auth development on in nest and I have hit another road block
So the user stores fine and has everything needed with bcrypt working great
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
export type UserDocument = User & Document;
#Schema()
export class User {
#Prop()
firstname: string;
#Prop()
lastname: string;
#Prop()
jobtitle: string;
#Prop()
startdate: string
#Prop()
password: string;
#Prop()
username: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
I have a auth service and auth controller
import { Injectable, NotAcceptableException } from '#nestjs/common';
import { UsersService } from '../users/users.service';
import * as bcrypt from 'bcrypt';
import { JwtService } from '#nestjs/jwt';
#Injectable()
export class AuthService {
constructor(private readonly usersService: UsersService, private jwtService: JwtService) { }
async validateUser(username: string, password: string): Promise<any> {
const user = await this.usersService.getUser({ username });
if (!user) return null;
const passwordValid = await bcrypt.compare(password, user.password)
if (!user) {
throw new NotAcceptableException('could not find the user');
}
if (user && passwordValid) {
return user;
}
return null;
}
async login(user: any) {
const payload = { username: user.username, sub: user._id };
return {
access_token: this.jwtService.sign(payload),
};
}
}
import { Controller, Request, Post, UseGuards } from '#nestjs/common';
import { AuthService } from './auth.service';
import { AuthGuard } from '#nestjs/passport';
#Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
// #UseGuards(AuthGuard('local'))
#Post('auth/login')
async login(#Request() req) {
return this.authService.login(req.user);
}
}
When I go to login function it gives me the error:
ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'username')
For context :
import { Injectable } from '#nestjs/common';
import { InjectModel } from '#nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from 'users/interfaces/users.interface';
#Injectable()
export class UsersService {
constructor(#InjectModel('Users') private readonly userModel: Model<User>) {}
//Get all users
async getUsers(): Promise<User[]> {
const users = await this.userModel.find().exec();
return users
}
//Get single user
async getUser(query: object ): Promise<User> {
return this.userModel.findOne(query);
}
async addUser(
firstname: string,
lastname: string,
jobtitle: string,
startdate: string,
password: string,
username: string): Promise<User> {
return this.userModel.create({
firstname,
lastname,
jobtitle,
startdate,
password,
username
});
}
}
and the local Strategy
import { Strategy } from 'passport-local';
import { PassportStrategy } from '#nestjs/passport';
import { Injectable, UnauthorizedException } from '#nestjs/common';
import { AuthService } from './auth.service';
#Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super();
}
async validate(username: string, password: string): Promise<any> {
const user = await this.authService.validateUser(username, password);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
I'm creating an input type for nestJs graphQL mutation. After providing the Input type to my mutation argument I'm getting this error
Input Type
import { Field, InputType } from '#nestjs/graphql';
import { IsDate, IsNotEmpty, IsString } from 'class-validator';
#InputType()
export class MasterManagementCreateInput {
#IsString()
#IsNotEmpty()
#Field(() => String)
masterNumber: string;
#IsString()
#IsNotEmpty()
#Field(() => String)
flightNumber: string;
#IsString()
#IsNotEmpty()
#Field(() => String)
departureAirPort: string;
#IsString()
#IsNotEmpty()
#Field(() => String)
arrivalAirPort: string;
#IsDate()
#Field(() => Date, { nullable: true })
DepartureTime: Date;
#IsDate()
#Field(() => Date, { nullable: true })
arrivalTime: Date;
#IsString()
#IsNotEmpty()
#Field(() => String)
deliveryStatus: string;
}
Resolver
import { Args, Query, Resolver, Mutation } from '#nestjs/graphql';
import { MasterManagement } from './entities';
import { MasterManagementService } from './master-management.service';
import { FindById } from '../dtos';
import { MasterManagementUpdateInput, MasterManagementCreateInput } from './dto';
#Resolver(() => MasterManagement)
export class MasterManagementResolver {
constructor(
private readonly masterManagementService: MasterManagementService,
) {}
#Query(() => [MasterManagement])
async allMasterManagement() {
return await this.masterManagementService.getAll();
}
#Query(() => MasterManagement)
async masterManagementById(#Args('id') id: FindById) {
return await this.masterManagementService.getById({ id });
}
#Mutation(() => MasterManagement)
async createMasterManagement(
#Args('createInput')
input: MasterManagementCreateInput,
) {
return await this.masterManagementService.create(input);
}
#Mutation(() => MasterManagement)
async updateMasterManagement(
#Args('updateInput') input: MasterManagementUpdateInput,
) {
const { id } = input;
delete input.id;
return await this.masterManagementService.update(input, { id });
}
}
I don't know why this error is ocurring. I already used the same logic in my other resolvers and it is working fine. The itresting part is if I use an #InputType from other resolvers in this resolver it works fine.
Calling 'localhost:3000/contacts' (with or without parameters) at postman returns me this error and i don't know why. My backend is connected to a PostgreSQL db.
TypeError: Cannot read property 'createQueryBuilder' of undefined
at ContactsRepository.Repository.createQueryBuilder (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\typeorm\repository\Repository.js:17:29)
at ContactsRepository.getContacts (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\dist\contacts\contacts.repository.js:17:34)
at ContactsService.getContacts (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\dist\contacts\contacts.service.js:24:39)
at ContactsController.getContacts (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\dist\contacts\contacts.controller.js:25:37)
at ...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\#nestjs\core\router\router-execution-context.js:38:29
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async ...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\#nestjs\core\router\router-execution-context.js:46:28
at async ...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\#nestjs\core\router\router-proxy.js:9:17
My code looks like this:
#EntityRepository(Contact)
export class ContactsRepository extends Repository<Contact> {
async getContacts(filterDto: GetContactsFilterDto): Promise<Contact[]> {
const { name, search } = filterDto;
// const query = this.createQueryBuilder('contacts');
const query = await this.createQueryBuilder()
.select('contacts')
.from(Contact, 'contacts');
if (name) {
query.andWhere('contacts.name = :name', { name });
}
if (search) {
query.andWhere(
'(contacts.email LIKE :search OR contacts.telephone LIKE :search)',
{ search: `%${search}%` },
);
}
const contacts = await query.getMany();
return contacts;
}
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
#Entity({ name: 'contacts' })
export class Contact extends BaseEntity {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
email: string;
#Column()
html_de: string;
#Column()
html_en: string;
#Column()
name: string;
#Column()
telephone: string;
}
export class ContactsController {
constructor(private contactsService: ContactsService) {}
#Get()
getContacts(
#Query(ValidationPipe) filterDto: GetContactsFilterDto,
): Promise<ContactDto[]> {
return this.contactsService.getContacts(filterDto);
}
#Injectable()
export class ContactsService {
constructor(
#InjectRepository(ContactsRepository)
private contactsRepository: ContactsRepository,
) {}
async getContacts(filterDto: GetContactsFilterDto): Promise<Contact[]> {
return this.contactsRepository.getContacts(filterDto);
}
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { ContactsController } from './contacts.controller';
import { ContactsRepository } from './contacts.repository';
import { ContactsService } from './contacts.service';
#Module({
controllers: [ContactsController],
imports: [TypeOrmModule.forFeature([ContactsRepository])],
providers: [ContactsRepository, ContactsService],
exports: [ContactsRepository, ContactsService],
})
export class ContactsModule {}
Somebody know how i can fix this? Regards
ContactsRepository should only be used in the TypeOrmModule.forFeature() and not added to the providers or exports array. When it is added here, the injection token for ContactsRepository no longer points to the proper instance and Nest creates the class, but doesn't have it properly extend Repository as that code is all managed by TypeORM
Hello folks I will keep my question very simpler by showing code
I am using Json placeholder site for the fake rest Api
I have a user class Object
I want to convert returned Observable to the
custom class object array.
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { Users } from './users.model';
#Injectable({
providedIn: 'root'
})
export class UsersService {
private url = "https://jsonplaceholder.typicode.com";
constructor(private http:HttpClient) {
console.log(this.getUsers());
}
getUsers():Observable<Users[]>{
return this.http.get<Users[]>(`${this.url}/posts`);
}
}
The above is my service
export class Users {
email: string;
id: number;
name: string;
phone: string;
username: string;
}
above is my class I haven't included all properties
In my typescript file I have code like.
constructor(private _usersService:UsersService) {
}
ngOnInit(): void {
this._usersService.getUsers().subscribe(data=>this.users=data);
console.log(this.users);
}
Now the things I want is
how to convert returned observable in my custom class object?
I don't have all the fields so how is it possible to map only those fields which I want?
Hope my question is clear..!!
so this answer takes advantage of map() which is imported from rxjs.
before subscribing we are going to pipe a map() function into the observable stream and then map() each element from that array into a new object that fits our User interface
then we subscribe and the data we get then will be an array that fits our User interface
ngOnInit(): void {
this._usersService.getUsers()
.pipe(map(data => {
return data.map(item => {
const user: User = {
name: item.name,
email: item.email,
}
return user
})
}))
.subscribe(data=>this.users=data);
console.log(this.users);
}
You can do like below, in the User class have a constructor and return User while mapping
import { Component, VERSION, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { map } from 'rxjs/operators';
export class User {
email: string;
id: number;
name: string;
phone: string;
username: string;
constructor( user: User ) {
Object.assign( this, user );
}
}
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular ' + VERSION.major;
constructor(private http: HttpClient){}
ngOnInit() {
this.http.get<User[]>("https://jsonplaceholder.typicode.com/users")
.pipe(
map( data => {
return data.map( ( user ) => {
return new User( {
email: user['email'],
id: user['id'],
name: user['name'],
phone: user['phone'],
username: user['username'],
} );
} );
} ),
)
.subscribe( (users : User[]) => console.log(users) );
}
}
Working stackblitz
I'm following a Angular and .net course.
I'm trying to set the photourl to a method.
I'm getting the following error\
Argument of type date is not assignable to parameter of type string
The error is on the following line.
this.changeMemberPhoto(this.currentUser.photoUrl);
The argument is the issue
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { JwtHelperService} from '#auth0/angular-jwt';
import { environment } from 'src/environments/environment';
import { User } from '../_models/user';
#Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl + 'auth/';
jwtHelpter = new JwtHelperService();
decodedToken: any;
currentUser: User;
photoUrl = new BehaviorSubject<string>('../../assets/user.png');
currentPhotoUrl = this.photoUrl.asObservable();
constructor(private http: HttpClient) {}
changeMemberPhoto(photoUrl: string) {
this.photoUrl.next(photoUrl);
}
login(model: any) {
return this.http.post(this.baseUrl + 'login', model).pipe(
map((response: any) => {
const user = response;
if (user) {
localStorage.setItem('token', user.token);
localStorage.setItem('user', JSON.stringify(user.user));
this.decodedToken = this.jwtHelpter.decodeToken(user.token);
this.currentUser = user.user;
this.changeMemberPhoto(this.currentUser.photoUrl);
}
})
);
}
register(model: any) {
return this.http.post(this.baseUrl + 'register', model);
}
loggedIn() {
const token = localStorage.getItem('token');
return !this.jwtHelpter.isTokenExpired(token);
}
}
The code is identical to the instructors, so I don't know what the issue is.
I've included the User class as requested
import { Photo } from './photo';
export interface User {
id: number;
username: string;
knownAs: string;
age: number;
gender: string;
created: Date;
lastActive: Date;
photoUrl: Date;
city: string;
country: string;
interests?: string;
introduction?: string;
lookingFor?: string;
photos?: Photo[];
}
photoUrl is a date in your class and is a string in your changeMemberPhoto method
In User class, change it to :
photoUrl: string;