Callback is not a function when remote method recursively calls itself - loopbackjs

i have the below code when it is called i get an error saying callback in not a function in the last instance of callback. ( callback("UnabletoSetAcessToken") )
serviceOffering.ResetToken = function (retried, Data, options, callback) {
var filterGetSH = 'Set Token';
retried++;
if (retried < 4) {
if (Data.hasOwnProperty('Name')) {
filterGetSH = { 'where': { 'Name': Data.Name } };
serviceOffering.setToken(retried, Data, filterGetSH, options, function (error, dataBody) {
if (error) {
serviceOffering.ResetToken(retried, Data, filterGetSH, options, callback);
} else {
callback(null, dataBody);
}
});
} else if (Data.hasOwnProperty('EntityId')) {
filterGetSH = { 'where': { 'EntityId': entityData.EntityId } };
serviceOffering.setToken(retried, Data, filterGetSH, options, function (error, dataBody) {
if (error) {
serviceOffering.ResetToken(retried, Data, filterGetSH, options, callback);
} else {
callback(null, dataBody);
}
});
}
} else {
callback("UnabletoSetAcessToken")
}
};
i expected the callback to get called if max retry has reached when unsuccessful. I am unable to understand what is wrong here and how to approach this.
NOTE:- here setToken is a different remote method that when successful with Oauth token or will return error message.

The signature of setToken and ResetToken does not match when calling.
serviceOffering.ResetToken = function (retried, Data, options, callback) {
var filterGetSH = 'Set Token';
retried++;
if (retried < 4) {
if (Data.hasOwnProperty('Name')) {
filterGetSH = { 'where': { 'Name': Data.Name } };
options.filter = filterGetSH;
serviceOffering.setToken(retried, Data, options, function (error, dataBody) {
if (error) {
serviceOffering.ResetToken(retried, Data, options, callback);
} else {
callback(null, dataBody);
}
});
} else if (Data.hasOwnProperty('EntityId')) {
filterGetSH = { 'where': { 'EntityId': Data.EntityId } };
options.filter = filterGetSH;
serviceOffering.setToken(retried, Data, options, function (error, dataBody) {
if (error) {
serviceOffering.ResetToken(retried, Data, options, callback);
} else {
callback(null, dataBody);
}
});
}
} else {
callback("UnabletoSetAcessToken")
}
};

Related

Cannot determine what is wrong with this action. Input Parameter is null

Using the following results in a null input error. Through debugging the plugin the input parameter is not being passed. Any ideas? I've done hundreds of these but never seen this type of issue.
tdn_GetFoxhoundNotesRequest = function (contactId) {
this.ContactId = contactId;
};
tdn_GetFoxhoundNotesRequest.prototype.getMetadata = function () {
return {
boundParameter: null,
parameterTypes: {
"ContactId": {
"typeName": "Edm.String",
"structurualProperty": 1
}
},
operationType: 0,
operationName: "tdn_GetFoxhoundNotes"
};
};
function LoadNotes(executionContext) {
var formContext = executionContext.getFormContext();
var contactId = formContext.data.entity.getId().replace("{", "").replace("}", "");
var request = new tdn_GetFoxhoundNotesRequest(contactId);
Xrm.WebApi.online.execute(request).then(
function success(result) {
if (result.ok) {
{
result.json().then(function (response) {
formContext.getAttribute("tdn_foxhoundnotestextblob").setValue(response.Notes);
formContext.getAttribute("tdn_foxhoundnotestextblob").setSubmitMode('never');
})
}
}
},
function (error) {
Xrm.Utility.alertDialog(error.message);
});
}

How to mock 'FirebaseAuth.instance'?

I want to start writing unit test to my flutter app that have developed using GetX pattern. In GetX pattern, the code is separated to controller and view, so all methods that I want to test is in controller.
In my app, I am using firebase to make authentication with mobile number.
This is LoginController:
class LoginController extends GetxService {
...
LoginController(this.authService);
final _auth = FirebaseAuth.instance;
String validatePhoneNumber(String phoneNumber) {
if (!phoneNumber.startsWith('+20')) {
return 'أدخل كود البلد مثل: +20 في مصر';
} else if (phoneNumber.length < 11) {
return 'أدخل رقم صحيح';
} else if (phoneNumber.isEmpty) {
return 'أدخل رقم الهاتف';
}
return null;
}
Future<void> validate() async {
await _auth.verifyPhoneNumber(
phoneNumber: phoneNumberController.text,
timeout: timeoutDuration,
codeAutoRetrievalTimeout: (String verificationId) {
verId.value = verificationId;
currentState.value = SignInPhoneWidgetState.CodeAutoRetrievalTimeout;
},
codeSent: (String verificationId, [int forceResendingToken]) {
verId.value = verificationId;
currentState.value = SignInPhoneWidgetState.CodeSent;
DialogService.to.stopLoading();
Get.toNamed(Routes.ACCEPT_SMS);
},
verificationCompleted: (AuthCredential phoneAuthCredential) async {
currentState.value = SignInPhoneWidgetState.Complete;
try {
if (authService.currentUser.value != null) {
await authService.currentUser.value
.linkWithCredential(phoneAuthCredential);
} else {
await _auth.signInWithCredential(phoneAuthCredential);
}
Get.offAllNamed(Routes.ROOTHOME);
//widget.onLoggedIn(authResult);
} on PlatformException catch (e) {
print(e);
errorCode.value = e.code;
errorMessage.value = e.message;
} catch (e) {
print(e);
} finally {
//.......
}
},
verificationFailed: (FirebaseAuthException error) {
errorCode.value = error.code;
errorMessage.value = error.message;
currentState.value = SignInPhoneWidgetState.Failed;
},
//forceResendingToken:
);
}
Future<void> validateSmsCode() async {
//_auth.
var cred = PhoneAuthProvider.credential(
verificationId: verId.value, smsCode: verifyCodeController.text);
try {
if (authService.currentUser.value != null) {
await authService.currentUser.value.linkWithCredential(cred);
} else {
await _auth.signInWithCredential(cred);
await Get.offAllNamed(Routes.ROOTHOME);
}
} on PlatformException catch (ex) {
errorCode.value = ex.code;
errorMessage.value = ex.message;
currentState.value = SignInPhoneWidgetState.Failed;
} on FirebaseAuthException catch (ex) {
errorCode.value = ex.code;
errorMessage.value = ex.message;
currentState.value = SignInPhoneWidgetState.Failed;
}
}
...
}
This is login_test.dart file:
I should mock every outside operation like firebase. But In this case I want to test validatePhoneNumber method, that checks if the phone number is valid or not. the method it self hasn't firebase operations. But, the method is called by a LoginController object, And this object it self has instance of FirebaseAuth.instance.
final _authSerive = AuthService();
main() async {
final loginController = LoginController(_authSerive);
setUp(() async {});
tearDown(() {});
group('Phone Validation', () {
test('Valid Email', () {
String result = loginController.validatePhoneNumber('+201001234567');
expect(result, null);
});
});
}
When I tried to run this test method, This error appeared.
Failed to load "D:\bdaya\ta7t-elbeet-client\test\login_test.dart":
[core/no-app] No Firebase App '[DEFAULT]' has been created - call
Firebase.initializeApp()
The reasen is:
This line in The LoginController:
final _auth = FirebaseAuth.instance;
I certainly know that I have to mock Firebase operations.
How to mock it in this case or, What should I do?

AWS Cognito: Custom Challenge with Retry

I am using Custom Challenge for MFA because i wanted to use Twilio instead of AMAZON SNS. i have successfully implemented it. It works fine but
When a user enters wrong OTP code. The user session is expired. means that he has to again provide phone number and request a OTP again. Whereas i want it to retry for atleast 3 time. before he need to request another OTP.
My Response verify trigger is as simple as below, is there something that we can do.
(event, context, callback) => {
if (event.request.privateChallengeParameters.answer == event.request.challengeAnswer) {
event.response.answerCorrect = true;
} else {
event.response.answerCorrect = false;
}
callback(null, event);
}
I acheived this by adding the answer as a variable into challengeMetaData - which so far as I can see is not returned to the client but is available on subsequent calls, I also have a variable named attempts to track how many times the user has entered an incorrect value.My code is below - I hope it helps
const AWS = require("aws-sdk");
exports.handler = (event, context, callback) => {
const session = event.request.session;
const currentSession = session ? session.length - 1 : 0
switch (event.triggerSource) {
case 'DefineAuthChallenge_Authentication':
console.log("DefineAuthChallenge_Authentication");
console.log(event);
if (session.length === 0) {
event.response = {
challengeName: 'CUSTOM_CHALLENGE',
failAuthentication: false,
issueTokens: false
};
}
else {
if (session[currentSession].challengeName === 'CUSTOM_CHALLENGE') {
if (session[currentSession].challengeResult === true) {
event.response.issueTokens = true;
event.response.failAuthentication = false;
}
else {
let metaData = JSON.parse(session[currentSession].challengeMetadata);
if (metaData.attempts <= 3) {
event.response = {
challengeName: 'CUSTOM_CHALLENGE',
failAuthentication: false,
issueTokens: false
};
}
else {
event.response.issueTokens = false;
event.response.failAuthentication = true;
}
}
}
}
console.log(event);
break;
case 'CreateAuthChallenge_Authentication':
if (event.request.challengeName === 'CUSTOM_CHALLENGE') {
console.log("CreateAuthChallenge_Authentication");
console.log(event);
if (session.length === 0) {
let answer = Math.random().toString(10).substr(2, 6);
//Your logic to send a message goes here
event.response.publicChallengeParameters = { challengeType: 'SMS_CODE' };
event.response.privateChallengeParameters = { answer: answer };
event.response.challengeMetadata = JSON.stringify({ '_sid': answer, 'challengeType': 'SMS_CODE', attempts: 1 });
}
else {
let metaData = JSON.parse(session[currentSession].challengeMetadata);
if (metaData.attempts <= 3) {
event.response.publicChallengeParameters = { challengeType: 'SMS_CODE', errorCode: 'NotAuthorizedException' };
event.response.privateChallengeParameters = { answer: metaData._sid };
event.response.challengeMetadata = JSON.stringify({ '_sid': metaData._sid, 'challengeType': 'SMS_CODE', attempts: metaData.attempts + 1 });
}
}
}
console.log(event);
break;
default:
console.log("VerifyAuthChallenge_Authentication");
console.log(event);
if (event.request.privateChallengeParameters.answer === event.request.challengeAnswer) {
event.response.answerCorrect = true;
}
else { event.response.answerCorrect = false; }
console.log(event);
break;
}
callback(null, event);
};

QUnit testing a function which leans on document properties

I'm trying to write some unit tests for an Apps Script add-on designed for Google Docs. A few of the functions I'd like to have unit tests for call PropertiesService.getDocumentProperties(). A simple example function in my add-on:
function baseFontSize() {
var baseFontSize = JSON.parse(
PropertiesService.getDocumentProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
baseFontSize = JSON.parse(
PropertiesService.getUserProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
PropertiesService.getUserProperties().setProperty('baseFontSize', '11');
baseFontSize = 11;
}
PropertiesService.getDocumentProperties()
.setProperty('baseFontSize', JSON.stringify(baseFontSize));
}
return baseFontSize;
}
I'm writing my tests with the QUnit for Google Apps Script library:
function doGet(e) {
QUnit.urlParams(e.parameter);
QUnit.config({title: 'My test suite'});
QUnit.load(testSuite);
return QUnit.getHtml();
}
QUnit.helpers(this);
function testSuite() {
// some module() and test() calls deleted for brevity...
test('baseFontSize', function() {
// PropertiesService.getDocumentProperties() === null
// how to test baseFontSize()?
});
// more module() and test() calls...
}
Since the test suite is not running within a document, there are no document properties. It seems that the only way to test my function would be to mock the getDocumentProperties function. Of course, the only Apps Script mock/stub libraries I can find are either meant to test within a Node.js environment, or are not sufficiently complete for my needs, which means I would have to roll my own.
While I still hope to find a more elegant solution, until that occurs I have thrown together a simple stub framework based on the SinonJS API, and I'm injecting the stub into my function to be tested (since I can't actually stub PropertiesService, as it's frozen).
Roughly, my solution (my project already includes Underscore, so I take advantage of it where I can):
function stub(object, property, impl) {
const original = object[property];
if (_.isFunction(impl)) object[property] = wrapFunction(impl);
else object[property] = wrapFunction(function() { return impl; });
object[property].restore = function() {
if (!_.isUndefined(original)) object[property] = original;
else delete object[property];
};
return object[property];
}
function wrapFunction(fn) {
const properties = _.mapObject({
get callCount() { return calls.length; },
get called() { return calls.length > 0; },
get notCalled() { return calls.length === 0; },
// etc...
}, function(v, k, o) { return Object.getOwnPropertyDescriptor(o, k); });
const calls = [];
const wrappedFn = function() {
const args = Array.prototype.slice.call(arguments);
var error;
var returnVal;
try { returnVal = fn.apply(this, args); }
catch (e) { error = e; }
calls.push({
thisObj: this,
params: args,
error: error,
returnVal: returnVal,
});
return returnVal;
};
Object.defineProperties(wrappedFn, properties);
return wrappedFn;
}
Then, my test:
test('baseFontSize', function() {
const propService = {};
stub(propService, 'getDocumentProperties', fakeGetProperties());
stub(propService, 'getUserProperties', fakeGetProperties());
equal(baseFontSize(propService), 11);
});
//...
function fakeGetProperties() {
const map = {};
const container = {
deleteAllProperties: function() {_.each(map, function(v, k){depete map[k];});},
deleteProperty: function(k) { delete map[k]; },
getKeys: function() { return Object.keys(map); },
getProperties: function() { return _.clone(map); },
getProperty: function(key) { return map[key] || null; },
setProperties: function(obj, deleteOthers) {
if (deleteOthers) container.deleteAllProerties();
_.each(obj, function(v, k) { map[k] = v; });
},
setProperty: function(key, value) { map[key] = value; },
};
return function() { return container; };
}
And the edited version of my function to test, with DI for PropertiesService:
function baseFontSize(propService) {
if (_.isUndefined(propService)) {
propService = PropertiesService;
}
var baseFontSize = JSON.parse(
propService.getDocumentProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
baseFontSize = JSON.parse(
propService.getUserProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
propService.getUserProperties().setProperty('baseFontSize', '11');
baseFontSize = 11;
}
propService.getDocumentProperties()
.setProperty('baseFontSize', JSON.stringify(baseFontSize));
}
return baseFontSize;
}

RxSwift Simple background task example

I have a method as following
public static func createAlbum(named: String, completion: (album: PHAssetCollection?) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
}) { success, error in
completion(album: album)
}
}
}
How can i do the background task using RxSwift
complete code
https://gist.github.com/sazzadislam-dsi/d347909d284674c936e397ac423703cf
#XFreire answer is right, but for Swift 3 and RxSwift 3.1.0 I would add an extension to PHAssetCollection:
extension Reactive where Base: PHPhotoLibrary {
func createAlbum(named name: String) -> Observable<PHAssetCollection?> {
return Observable.create { observer in
self.base.performChanges({
// ...
}, completionHandler: { success, error in
if success {
// Your success logic goes here
let album = PHAssetCollection()
// ...
observer.on(.next(album))
observer.on(.completed)
} else if let error = error {
observer.on(.error(error))
} else {
// Your error type
observer.on(.error(MyErrors.Unknown))
}
})
return Disposables.create()
}
}
}
Then you can use the method like this:
PHPhotoLibrary
.shared().rx.createAlbum(named: "MyAlbum")
.subscribe(onNext: { collection in
// ...
}, onError: { error in
// ...
})
.addDisposableTo(disposeBag)
First, your function must return an Observable.
public static func rx_createAlbum(named: String)-> Observable<PHAssetCollection?>
Second, when there is an error, your function will return onError, and when success is true, your function will return onNext(album) and onCompleted().
Code:
public static func rx_createAlbum(named: String)-> Observable<PHAssetCollection?> {
return Observable.create { observer in
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
// ...
}) { success, error in
if error {
observer.onError(error)
}
else {
var album: PHAssetCollection?
if success {
let collectionFetchResult = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([placeholder?.localIdentifier ?? ""], options: nil)
album = collectionFetchResult.firstObject as? PHAssetCollection
}
observer.onNext(album)
observer.onCompleted()
}
}
}
return Disposables.create()
}
}