I have a BeforeInsert and AfterInsert hook that is not being called. All it does is log hook. I am using nestjs-graphql.
You can run this example doing npm i, then sending a mutation (playground is at localhost:3000/graphql) with body createUser(createInput:{password:"password" email:"test#test.com"}). It should succeed and log hook.
The hook (nothing is logged):
#Entity('user')
export default class UserEntity {
#PrimaryGeneratedColumn()
id: number;
#Column()
#IsEmail()
email: string;
#Column()
#Length(7, 42)
password: string;
#BeforeInsert()
#AfterInsert()
async validate() {
console.log("hook")
}
}
It's called from a service. The insertion does not throw an error, and here2 is logged:
#Injectable()
export class UserService {
constructor(
#InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
) { }
async createNew(email: string, password: string): Promise<number> {
console.log("here2")
const hashedPassword = "test"
const res = await this.userRepository.insert({ email, password: hashedPassword })
return res.identifiers[0].id
}
}
According to TypeORM's Docs the listener hooks get called before or after their respective operation when using the entity manager or repository's save method. As insert and similar operations don't call save, they don't execute the #Before/After* methods
#Injectable()
export class UserService {
constructor(
#InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
) { }
async createNew(email: string, password: string): Promise<number> {
const res = await this.userRepository.insert(Object.assign(new userRepository(), { email, password: hashedPassword }))
return res
}
}
Try like this
Related
i'm testing new InjectFirebaseAdmin from 'nestjs-firebase', i try to mock the function thats return me a verifyidToken but with out succes.
injectUser.ts
import { FirebaseAdmin, InjectFirebaseAdmin } from 'nestjs-firebase';
#Injectable()
export class InjectUser implements NestMiddleware {
constructor(
private readonly usersService: UsersService,
#InjectFirebaseAdmin() private readonly firebase: FirebaseAdmin // private firebaseAuth: FirebaseAuthenticationService
) {}
extractTokenFromHeaders(headers: IncomingHttpHeaders): string | undefined {
return headers.authorization?.split('Bearer ')[1];
}
async use(
req: AuthenticatedRequest,
res: Response,
next: () => void
): Promise<void> {
const token = this.extractTokenFromHeaders(req.headers);
if (token !== undefined) {
try {
const decodedToken = await this.firebase.auth.verifyIdToken(token);
req.uuid = decodedToken.uid;
} catch (error) {
throw isUnauthorizedHttpException();
}
const user = await this.usersService.getUserInfoFromAuthenticationId(
req.uuid
);
if (user) {
req.user = user;
}
}
next();
}
}
I would like to know how can i mock this function ? i use to try whith moduleRef.get(InjectFirebaseAdmin) but my spyOn function but i got this error : TypeError: Cannot read property 'auth' of undefined
Thanks for helping me
I am integrating Nestjs with firebase admin, the controller is not updating the view. With the service there is not problem, update in real time.
Someone will have some suggestion, what is my wrong in the code?
The Service that inject the controller is:
import { Injectable } from '#nestjs/common';
import * as admin from 'firebase-admin';
export interface Customer {
direction: string,
codLegal: string,
phone: string,
name: string
}
export interface CustomerId extends Customer{
id: string;
}
#Injectable()
export class CustomerService {
constructor() {}
findCustomers(): Promise<any>{
return new Promise((resolve, reject) => {
admin.firestore().collection('/data/LYvBew5FDpjLqcQjA2Ra/info')
.onSnapshot((querySnapshot) => {
const promises: any = [];
querySnapshot.forEach((doc: any) => {
promises.push({
id: doc.id,
data: doc.data() as Customer,
});
});
console.log(promises);
resolve(promises);
})
});
}
}
**The basic controller is: **
import { Controller, Get } from '#nestjs/common';
import { CustomerService } from './services/customer.service';
#Controller('customers') export class CustomerController {
constructor(private readonly customerService: CustomerService) {
}
#Get()
async findAll() {
try {
return await this.customerService.findCustomers();
}catch(err) {
console.log(err);
}
}
}
Talking in terms of HTTP, the controller will not update the view. The view is rendered once you call the findAll route and send to the client.
If you want to show updates to the view in realtime, you should include firebase into your frontend.
I am unable to read data from Firebase using angularfireobject.
This is my code:
export class UserService {
user: Observable<any>;
constructor(private db: AngularFireDatabase) {
}
public getUser($userId: string){
this.db.object('users/'+$userId).valueChanges();
}
}
and in user.component.html
<h1>Welcome {{ (userService.user | async)?.name }}!</h1>
userService.user | json gives null.
Any help is appreciated.
You're not setting your .user Observable anywhere that I see and .getUser() is never called.
If you intend to show information on the current user you'll have to pull in authentication too:
export class UserService {
user: Observable<any>;
constructor(private db: AngularFireDatabase, private auth: AngularFireAuth) {
this.user = auth.user.pipe(switchMap(user =>
user ? db.object(`users/${user.uid}`).valueChanges() : of(null)
));
}
}
Maybe I am over thinking it, but I can't figure out a way to put the results of a Firestore query into a Polymer 3 template. For example:
class MyPage extends PolymerElement {
constructor() {
super();
/* somehow set this.users to the firestore users query results */
}
static get properties() {
return {
users: {
type: String
}
}
}
static get template() {
return html`<div>[[users]]</div>`;
}
}
Using the following code, which does work correctly and print to the console:
var all_users;
const setsRef = firestore.collection("users");
setsRef.get().then(function(querySnapshot) {
var users = [];
querySnapshot.forEach(function(doc) {
users.push(doc.data().verb);
});
all_users = users.join(", ");
console.log("All users: ", all_users);
/* run a function here that sets this.users = all_users */
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
The problem is, I have to run a function from the Firestore results, while the other is a constructor of an object. I would preferably like to have all of my Firebase queries in an external js file, but this async thought process is confusing me.
Use one of the lifecycle methods to load the users:
https://www.polymer-project.org/3.0/docs/devguide/custom-elements#element-lifecycle
class MyPage extends PolymerElement {
constructor() {
super();
this.users = []
}
static get properties() {
return {
users: {
type: String
}
}
}
static get template() {
return html`<div>[[users]]</div>`;
}
async ready() {
super.ready()
try {
const querySnapshot = await firestore.collection("users").get()
this.users = querySnapshot.map(doc => doc.data().verb).join(", ");
} catch (error) {
console.log(error)
}
}
}
If you don't want to use one of the lifescycle methods, then you can fire your own custom event which your MyPage element can listen for: https://www.polymer-project.org/3.0/docs/devguide/events#custom-events
I'm not familiar with Polymer, so the above is untested and what I figure from reading the docs.
I'm trying to apply reflux/ngrx on my current front-end project.
I want to take advantage of this in order to change a slight functionality: Change current user related tasks in order to use a single user state.
Current user related tasks: Currently, I'm using an traditional model in order to achieve user login process... UserService is able to check user credentials. Once it's been checked I store user information on an AppService:
export class LoginComponent implements OnInit {
private fb: FormBuilder;
private form:FormGroup;
private commty: UsersService;
private router: Router;
private appState: AppState;
private alerts: Array<Object>;
constructor()
{
this.alerts = [];
}
ngOnInit():void {
this.form = this.fb.group({
user: ['', Validators.required],
passwd: ['', Validators.minLength(6)]
});
}
public checkPasswd():void {
this.clearAlerts();
this.commty.checkPasswd(this.form.value.mail, this.form.value.passwd)
.subscribe(
(result: any) => {
this.appState.user = result;
this.router.navigate(['/app']);
},
(error: any) => {
this.addAlert(error.message);
}
);
}
private addAlert(message: string): void {
this.alerts.push({type: 'danger', msg: message});
}
public closeAlert(index): void {
this.alerts.splice(index, 1);
};
private clearAlerts(): void {
this.alerts.splice(0, this.alerts.length);
}
}
I'm a bit confused about how to move this code in order to use reflux/ngrx. I'ce read a bit about this topic, nevertheless I'm not quite able to figure out how to move my code. Up to now, I've created an single Store and User interfaces:
store.interface.ts:
export interface IStore {
user: IUser
sources: ISourceRedux;
}
user.interfcae.ts:
export interface IUser {
id: string;
name: string;
username: string;
customer: string;
}
The next step I think I need to do is to create reducers. This step is which I don't quite understand how build this code. Up to now
user.initialstate.ts:
export function initialUserState(): IUser {
return {
id: '',
name: '',
username: '',
customer: '',
sources: []
};
};
user.reducer.ts
export class User {
private static reducerName = 'USER_REDUCER';
public static reducer(user = initialUserState(), {type, payload}: Action) {
if (typeof User.mapActionsToMethod[type] === 'undefined') {
return user;
}
return User.mapActionsToMethod[type](user, type, payload);
}
// ---------------------------------------------------------------
// tslint:disable-next-line:member-ordering
private static mapActionsToMethod = {};
}
Which reducers I should create in order to:
Check credentials.
If credentials are right get this user and update User state store.
If credentials are wrong inform the process has failed.
Perhaps I'm merging concepts... I need some lights...
EDIT
public connect(user: string, currentPasswd: string, extraHttpRequestParams?: any): Observable<UserDTO> {
return this.checkPasswdWithHttpInfo(id, currentPasswd, extraHttpRequestParams)
.map((response: Response) => {
if (response.status === 204) {
return undefined;
} else {
return response.json();
}
}).catch((error: any) => {
if (error.status >= 500) {
return Observable.throw(new Error(error.status));
}
else { //if (error.status >= 400) {
const body = error.json() || '';
const code = body.error || JSON.stringify(body);
const message = body.message || JSON.stringify(body);
return Observable.throw(ApiError.create(code, message));
}
});
}
Ok so this is the next question of your "Integrate ngrx into my code" =).
What you're looking for is : https://github.com/ngrx/effects
The idea behind effects is that an effect let you catch an Action, do side effect (API call or whatever) and you can then dispatch another Action (often success or error).
Flow example to connect a user :
--| [from component] Dispatch action USER_CONNECT
--| [from user.effect.ts]
----| Catch action ofType('USER_CONNECT')
----| Do what you need to do (API call for ex)
----| When the response comes back :
------| If success : Dispatch USER_CONNECT_SUCCESS
------| If error : Dispatch USER_CONNECT_ERROR
Of course when you dispatch either USER_CONNECT_SUCCESS or USER_CONNECT_ERROR you can pass additional data in the payload (for example user information or the error).
Here's a full example :
#Injectable()
export class UsersEffects {
constructor(
private _actions$: Actions,
private _store$: Store<IStore>,
private _userService: UserService,
) { }
#Effect({ dispatch: true }) userConnect$: Observable<Action> = this._actions$
.ofType('USER_CONNECT')
.switchMap((action: Action) =>
this._userService.connect(action.payload.username, action.payload.password)
.map((res: Response) => {
if (!res.ok) {
throw new Error('Error while connecting user !');
}
const rslt = res.json();
return { type: 'USER_CONNECT_SUCCESS', payload: rslt };
})
.catch((err) => {
if (environment.debug) {
console.group();
console.warn('Error catched in users.effects.ts : ofType(USER_CONNECT)');
console.error(err);
console.groupEnd();
}
return Observable.of({
type: 'USER_CONNECT_ERROR',
payload: { error: err }
});
})
);
}
You can take a look into my project Pizza-Sync were I did something similar (except that I don't catch in case of error and do not dispatch if there's an error).