How do we get android token on ionic 4? - ionic-framework

Hello i'm using fcm ionic native plugin, its working well with android 7 and below but on android 8 Oreo and above it can't get the device token, what could be the problem?

You can use the code below and hope it works out for you:
export interface AuthResponseData {
kind: string;
idToken: string;
email: string;
refreshToken: string;
localId: string;
expiresIn: string;
registered?: boolean;
}
export class AuthService implements OnDestroy {
private _user = new BehaviorSubject<User>(null);
get token() {
return this._user.asObservable().pipe(
map(user => {
if (user) {
return user.token;
} else {
return false;
}
})
);
}
constructor(private http: HttpClient) { }
signup(email: string, password: string) {
return this.http
.post<AuthResponseData>(
`https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${yourAPIKey}`,
{ email, password, returnSecureToken: true })
.pipe(tap(this.setUserData.bind(this)));
}
login(email: string, password: string) {
return this.http
.post<AuthResponseData>(
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${yourAPIKey}`,
{ email, password, returnSecureToken: true })
.pipe(tap(this.setUserData.bind(this)));
}
private setUserData(userData: AuthResponseData) {
const expirationTime = new Date(new Date().getTime() + +userData.expiresIn * 1000);
const user = new User(userData.localId, userData.email, userData.idToken, expirationTime);
this._user.next(user);
this.storeAuthData(userData.localId, userData.idToken, expirationTime.toISOString(), userData.email);
}
private storeAuthData(userId: string, token: string, tokenExpirationDate: string, email: string) {
const data = JSON.stringify({ userId, token, tokenExpirationDate, email });
Plugins.Storage.set({ key: 'authData', value: data });
}
}
And you can use this link for more information

Related

Mongoose Schema properties validation with Typescript NextJS

i am trying to save new document to mongo db, the Schema validation is not working for me, i am trying ti make required true, but i still can add new document without the required field.
this is my schema:
// lib/models/test.model.ts
import { Model, Schema } from 'mongoose';
import createModel from '../createModel';
interface ITest {
first_name: string;
last_name: string;
}
type TestModel = Model<ITest, {}>;
const testSchema = new Schema<ITest, TestModel>({
first_name: {
type: String,
required: [true, 'Required first name'],
},
last_name: {
type: String,
required: true,
},
});
const Test = createModel<ITest, TestModel>('tests', testSchema);
module.exports = Test;
this is createModel:
// lib/createModel.ts
import { Model, model, Schema } from 'mongoose';
// Simple Generic Function for reusability
// Feel free to modify however you like
export default function createModel<T, TModel = Model<T>>(
modelName: string,
schema: Schema<T>
): TModel {
let createdModel: TModel;
if (process.env.NODE_ENV === 'development') {
// In development mode, use a global variable so that the value
// is preserved across module reloads caused by HMR (Hot Module Replacement).
// #ts-ignore
if (!global[modelName]) {
createdModel = model<T, TModel>(modelName, schema);
// #ts-ignore
global[modelName] = createdModel;
}
// #ts-ignore
createdModel = global[modelName];
} else {
// In production mode, it's best to not use a global variable.
createdModel = model<T, TModel>(modelName, schema);
}
return createdModel;
}
and this is my tests file:
import { connection } from 'mongoose';
import type { NextApiRequest, NextApiResponse } from 'next';
const Test = require('../../../lib/models/test.model');
import { connect } from '../../../lib/dbConnect';
const ObjectId = require('mongodb').ObjectId;
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
switch (req.method) {
case 'POST': {
return addPost(req, res);
}
}
}
async function addPost(req: NextApiRequest, res: NextApiResponse) {
try {
connect();
// const { first_name, last_name } = req.body;
const test = new Test({
first_name: req.body.first_name,
last_name: req.body.last_name,
});
let post = await test.save();
// return the posts
return res.json({
message: JSON.parse(JSON.stringify(post)),
success: true,
});
// Erase test data after use
//connection.db.dropCollection(testModel.collection.collectionName);
} catch (err) {
//res.status(400).json(err);
res.status(400).json({
message: err,
success: false,
});
}
}
in the Postman, i send a request body without the required field (first_name) and i still can add it.
any help?

Cypress & Microsoft Authentication don't work properly

I am trying to launch a Microsoft authentication via Cypress following the authentication structure proposed by Juunas11 available here (demo on youtube).
However, the request sent to the microsoft authority falls in timeout at the first execution. The following ones are launched without any problem.
Would there be a better way to manage this Microsoft authentication?
Below, the whole of my code written in a step definition but which will be inserted later in a Cypress command.
import { sign, decode, JwtPayload } from 'jsonwebtoken';
Given('le conseiller {string}', () => {
let cachedTokenExpiryTime = new Date().getTime();
let cachedTokenResponse: any = null;
if (cachedTokenExpiryTime <= new Date().getTime()) {
cachedTokenResponse = null;
}
const { tenantId, clientId, clientSecret, apiScopes, username, password } = Cypress.env('loginMicrosoft');
const authority = `https://login.microsoftonline.com/${tenantId}`;
const environment = 'login.windows.net';
const buildAccountEntity = (
homeAccountId: string,
realm: string,
localAccountId: string,
clientInfo: object,
username: string,
name: string
) => {
return {
authorityType: "MSSTS",
clientInfo: sign(clientInfo, clientSecret).split('.')[1],
homeAccountId,
environment,
realm,
localAccountId,
username,
name
};
};
const buildIdTokenEntity = (homeAccountId: string, idToken: string, realm: string) => {
return {
credentialType: "IdToken",
homeAccountId,
environment,
clientId,
secret: idToken,
realm,
};
};
const buildAccessTokenEntity = (
homeAccountId: string,
accessToken: string,
expiresIn: number,
extExpiresIn: number,
realm: string,
scopes: string[]
) => {
const now = Math.floor(Date.now() / 1000);
return {
homeAccountId,
credentialType: 'AccessToken',
secret: accessToken,
cachedAt: now.toString(),
expiresOn: (now + expiresIn).toString(),
extendedExpiresOn: (now + extExpiresIn).toString(),
environment,
clientId,
realm,
target: scopes.map((s) => s.toLowerCase()).join(' '),
tokenType: 'Bearer'
};
};
const injectTokens = (tokenResponse: any) => {
const idToken: JwtPayload = decode(tokenResponse.access_token) as JwtPayload;
const localAccountId = idToken.oid || idToken.sid;
const realm = idToken.tid;
const homeAccountId = `${localAccountId}.${realm}`;
const name = idToken.name;
const clientInfo = {
"uid": localAccountId,
"utid": realm
}
const accountKey = `${homeAccountId}-${environment}-${realm}`;
const accountEntity = buildAccountEntity(
homeAccountId,
realm,
localAccountId,
clientInfo,
username,
name
);
const idTokenKey = `${homeAccountId}-${environment}-idtoken-${clientId}-${realm}--`;
const idTokenEntity = buildIdTokenEntity(
homeAccountId,
tokenResponse.id_token,
realm
);
const accessTokenKey = `${homeAccountId}-${environment}-accesstoken-${clientId}-${realm}-${apiScopes.join('')}-`;
const accessTokenEntity = buildAccessTokenEntity(
homeAccountId,
tokenResponse.access_token,
tokenResponse.expires_in,
tokenResponse.ext_expires_in,
realm,
apiScopes
);
const msalAccountCle = `msal.${clientId}.active-account`;
const msalAccountEntitee = localAccountId;
cy.window().then((win) => {
win.localStorage.setItem(accountKey, JSON.stringify(accountEntity));
win.localStorage.setItem(idTokenKey, JSON.stringify(idTokenEntity));
win.localStorage.setItem(accessTokenKey, JSON.stringify(accessTokenEntity));
win.localStorage.setItem(msalAccountCle, msalAccountEntitee);
})
};
const login = (cachedTokenResponse: any) => {
let tokenResponse: any = null;
let chainable: Cypress.Chainable = cy.visit('');
if (!cachedTokenResponse) {
chainable = chainable.request({
url: `${authority}/oauth2/v2.0/token`,
method: 'POST',
body: {
grant_type: 'password',
client_id: clientId,
client_secret: clientSecret,
scope: 'openid profile user.read',
username: username,
password: password,
},
timeout: 120000,
form: true,
log: true,
retryOnStatusCodeFailure: true,
retryOnNetworkFailure: true
});
} else {
chainable = chainable.then(() => {
return {
body: cachedTokenResponse,
};
});
}
chainable
.then((response) => {
console.log('réponse de microsoft : ', response.allRequestResponses);
injectTokens(response.body);
cy.window().then((win) => {
expect(win.localStorage.length).to.be.gte(0);
});
tokenResponse = response.body;
cy.getCookies().log;
})
.visit('')
.then(() => {
return tokenResponse;
})
.waitUntil(() => cy.get('.header-sub'));
return chainable;
};
login(cachedTokenResponse)
.then((tokenResponse) => {
cachedTokenResponse = tokenResponse;
cachedTokenExpiryTime = new Date().getTime() + 50 * 60 * 1000;
});
});

Cannot read property forEach of undefined

The title of this question is just the error I am currently receiving, but what I really need help with is understanding observables and API calls. For whatever reason, I just haven't been able to get a good grasp of this concept, and I am hoping that someone might have an explanation that will finally click.
I am trying to create a new Angular service that retrieves JSON from an API. I then need to map the response to a model. Due to weird naming conventions, job descriptions and job requirements are used interchangeably here. Here is my service class.
import { CommunicationService } from './communication.service';
import { AiDescription } from '../models/ai-description.model';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class AiDescriptionService {
requirements: Observable<AiDescription[]>;
private aiDescriptionUrl: string = '/api/core/company/jobdescriptions';
private dataStore: {
requirements: AiDescription[]
};
private _requirements: BehaviorSubject<AiDescription[]>;
private emptyRequestParams = {
"company_id": "",
"carotene_id": "",
"carotene_version": "",
"city": "",
"state": "",
"country": ""
};
readonly caroteneVersion: string = "caroteneV3";
constructor(
private communicationService: CommunicationService
) {
this.dataStore = { requirements: [] };
this._requirements = new BehaviorSubject<AiDescription[]>([]);
this.requirements = this._requirements.asObservable();
}
LoadRequirements(params: Object) {
this.communicationService.postData(this.aiDescriptionUrl, params)
.subscribe(res => {
let jobDescriptions = [];
jobDescriptions = res.jobdescriptions;
jobDescriptions.forEach((desc: { id: string; description: string; }) => {
let aiDescription = new AiDescription();
aiDescription.id = desc.id;
aiDescription.description = desc.description;
});
this.dataStore.requirements = res;
this._requirements.next(Object.assign({}, this.dataStore).requirements);
});
}
CreateRequest(
companyID : string,
caroteneID : string,
city: string,
state: string,
country: string
): Object {
let newRequestParams = this.emptyRequestParams;
newRequestParams.company_id = companyID;
newRequestParams.carotene_id = caroteneID;
newRequestParams.carotene_version = this.caroteneVersion;
newRequestParams.city = city;
newRequestParams.state = state;
newRequestParams.country = country;
this.LoadRequirements(newRequestParams);
return this.dataStore;
}
}
The postData() function being called by this.communicationService is here:
postData(url: string, jobInformation: any): Observable<any> {
const start = new Date();
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
const body = JSON.stringify(jobInformation);
const options = { headers };
return this.http.post(url, body, options)
.catch(err => Observable.throw(err))
.do(() => {
this.analyticsLoggingService.TrackTiming('JobPostingService', 'PostSuccess', new Date().getTime() - start.getTime());
}, () => {
this.analyticsLoggingService.TrackError('JobPostingService', 'PostFailure');
});
}
I didn't write the postData function, and I would not be able to modify it. When running a unit test, I am getting this error: "TypeError: Cannot read property 'forEach' of undefined".
But more than simply fixing the error, I am really trying to get a better understanding of using Observables, which is something I haven't been able to get a good understanding of from other sources.
In your example, I recommend replacing any and Object with explicitly defined models.
Here's an example for Angular 8 for Subscription, Promise, and Observable API calls. You can get more info here: https://angular.io/tutorial/toh-pt6.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs';
import { User } from './user.model';
#Injectable({ providedIn: 'root' })
export class UserService {
users: User[];
authHeaders = new HttpHeaders()
.set('Content-Type', 'application/json');
constructor(
private readonly http: HttpClient
) { }
getUsers() {
this.http.get(`https://myApi/users`, { headers: this.authHeaders })
.subscribe(
(data: User[]) => {
this.users = data;
}, (error: HttpErrorResponse) => { /* handle error */ });
}
async getUserPromise(userID: number): Promise<User> {
const url = `https://myApi/users/${userID}`;
return this.http.get<User>(url, { headers: this.authHeaders })
.toPromise();
}
getUserObservable(userID: number): Observable<User> {
const url = `https://myApi/users/${userID}`;
return this.http.get<User>(url, { headers: this.authHeaders });
}
}
I like to keep my class models in separate files. This example would have user.model.ts with content like:
export class User {
constructor(
public id: number,
public username: string,
public displayName: string,
public email: string
) { }
}
I've not included authentication headers or error handling for brevity; however, you might want to add those as needed.

Mongodb remove objects

I have the following code:
Log.ts
import * as mongoose from "mongoose";
import ILog = require("./ILog");
interface ILogModel extends ILog, mongoose.Document { }
var logSchema = new mongoose.Schema({
title: String,
description: String,
date: Date,
});
var log = mongoose.model<ILogModel>("Log", logSchema);
export = log;
ILog.ts
interface ILog {
title: string;
description: string;
date: Date;
};
export = ILog;
In my app I generate Logs with the following code:
var log = {
title: "tag",
description: "test",
date: Date.now()
};
Log.create(log, function (err: any, remote: any) {
});
But when I do Log.remove( { }) nothing happens.
In ROBO 3T if I do db.getCollection('logs').remove({})
the log is cleared, but I don't understand how to do it in the app
Please help.
Log.remove({}, function (err: any) {
if (err) return console.log("err", err);
});
did the trick

Angular 2: Create objects from a class

Hello I'm wondering if it's possible to create a class where you implement an interface and from there you send the data get from .get service to create a new object. Something like this
import { Component, OnInit } from '#angular/core';
import { User} from '../interfaces/user';
import {UserService} from '../services/user.service';
import { UserClass } from '../classes/user-class'
#Component({
selector: 'up-pros',
templateUrl: './pros.component.html',
providers: [UserService]
})
export class ProsComponent implements OnInit {
public users :User[];
public term: string;
constructor(private _httpService: UserService) { }
ngOnInit() {
console.log(UserClass)
this.term= 'INSTRUCTOR';
this._httpService.searchUsers(this.term)
.subscribe(
data => {this.users = new UserClass(data), console.log(data)},
error => alert(error + ' Error Get')
);
}
}
where my UserClass code is something like next one
import { User } from '../interfaces/user';
import { Address } from "../interfaces/address";
export class UserClass implements User {
public id: number
public name: string
public password: string
public lastNameA: string
public lastNameB: string
public photo: string
public telephone: string
public email: string
public userType: string
public active: string
public score: number
public createdAt: string
public updatedAt: string
public Address: Address
constructor ( id: number,
password: string,
name: string,
lastNameA: string,
lastNameB: string,
photo: string,
telephone: string,
email: string,
userType: string,
active: string,
score: number,
createdAt: string,
updatedAt: string,
Address: Address) {
this.name = name
this.password = password
this.lastNameA = lastNameA
this.lastNameB = lastNameB
this.photo = photo
this.telephone = telephone
this.email = email
this.userType = userType
this.active = active
this.score = score
this.createdAt = createdAt
this.updatedAt = updatedAt
this.Address = Address
}
}
and by the last, the interface:
import { Address } from "./address"
export interface User {
name: string;
password: string;
lastNameA: string;
lastNameB: string;
photo: string;
telephone: string;
email: string;
userType: string;
active: string;
score: number;
createdAt: string;
updatedAt: string;
Address: Address;
}
Is this possible? because if I try to do this Im getting the next error at pros-component.ts:
Supplied parameters do not match any signature of call target.
[default] Checking finished with 1 errors
My service:
import {Injectable} from '#angular/core';
import {Http, Headers} from '#angular/http';
import 'rxjs/add/operator/map';
import { User } from '../interfaces/user';
#Injectable()
export class UserService {
url= 'http://localhostapi/users';
constructor(private _http: Http){}
getUsers(){
return this._http.get(this.url)
.map(res => res.json());
}
searchUsers(term : string ){
return this._http.get('http://localhostapi/listas?user='+term)
.map(res => res.json());
}
searchUser(term : string ){
return this._http.get('http://localhostapi/users/'+term)
.map(res => res.json());
}
postUsers(user: User){
var headers = new Headers ();
headers.append('Content-Type','application/json');
return this._http.post(this.url, user, {headers: headers})
.map(res => res.json());
}
updateUsers(user: User, term: string){
var headers = new Headers ();
headers.append('Content-Type','application/json');
return this._http.put(this.url+"/"+term, user, {headers: headers})
.map(res => res.json());
}
}
If the structure of data matches the list of UserClass, you can simply do
this._httpService.searchUsers(this.term)
.subscribe(
data => {
this.users = data as User[];
console.log(data)
},
error => alert(error + ' Error Get')
);