ldapjs connecting to LDAP (ldap.forumsys.com) fails - ldap

Here is an online LDPA test server, http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
So I did some simple script to test it but I am always getting unwanted response.
Here is my code:
const ldap = require('ldapjs');
const assert = require('assert');
// LDAP Connection Settings
const server = "ldap.forumsys.com";
const uid = "tesla"
const password = "password"; // User password
// Create client and bind to AD
const client = ldap.createClient({
url: `ldap://${server}`
});
// Search AD for user
const searchOptions = {
filter: '(uid=${uid})'
};
// client.bind(`uid=tesla,dc=example,dc=com`,password,err => {
// assert.ifError(err);
// });
client.search(`cn=read-only-admin,dc=example,dc=com`,searchOptions,(err,res) => {
assert.ifError(err);
res.on('searchEntry', entry => {
console.log(entry.object.name);
});
res.on('searchReference', referral => {
console.log('referral: ' + referral.uris.join());
});
res.on('error', err => {
console.error('error: ' + err.message);
});
res.on('end', result => {
console.log(result);
});
});
// Wrap up
client.unbind( err => {
assert.ifError(err);
});
And I am getting this back by running the app.js
SearchResponse {
messageID: 1,
protocolOp: 101,
controls: [],
log:
Logger {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
_isSimpleChild: true,
_level: 30,
streams: [ [Object] ],
serializers: { req: [Function], res: [Function], err: [Function] },
src: false,
fields:
{ name: 'ldapjs',
component: 'client',
hostname: 'will-ThinkPad-T440p',
pid: 17485,
clazz: 'Client' } },
status: 0,
matchedDN: '',
errorMessage: '',
referrals: [],
connection:
Socket {
connecting: false,
_hadError: false,
_handle:
TCP {
reading: true,
owner: [Circular],
onread: [Function: onread],
onconnection: null,
writeQueueSize: 0 },
_parent: null,
_host: 'ldap.forumsys.com',
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: [Object],
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: false,
endEmitted: false,
reading: false,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events:
{ finish: [Function: onSocketFinish],
_socketEnd: [Function: onSocketEnd],
data: [Function: onData],
close: [Object],
end: [Function: onEnd],
error: [Function: onSocketError],
timeout: [Function: onTimeout] },
_eventsCount: 7,
_maxListeners: undefined,
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: false,
errorEmitted: false,
bufferedRequestCount: 0,
corkedRequestsFree: [Object] },
writable: true,
allowHalfOpen: false,
_bytesDispatched: 79,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
[Symbol(asyncId)]: 8,
[Symbol(bytesRead)]: 0 },
attributes: [],
notAttributes: [],
sentEntries: 0 }
which does not contain any information around "Tesla"......

Could be that this section:
// Search AD for user
const searchOptions = {
filter: '(uid=${uid})'
};
Needs backticks like the url settings above? If this is a dynamic value, you should add those to transform it into a string literal, like:
// Search AD for user
const searchOptions = {
filter: `(uid=${uid})`
};

const searchOptions = {
filter: '(uid=${uid})'
};
The above section is incorrect.
Should be
const searchOptions = {
filter: `(uid=${uid})`
};
I see Gustav as already given the correct answer. But adding to that the reason is when using ' the variable replacement does not happen as you have expected. to build the string like this you need to use `
Anyway since you have written an LDAP test server, there are already written test servers to achieve that, for example, you can use
https://hub.docker.com/r/upekshejay/simple-ldap-test-server

Related

Why does Array.push not work on arrays with Vuelidatevalidations?

I have multiple formArrays inside a form variable. On adding vuelidate validations to these formArrays/collections, Array.push doesn't work properly.
FormArray and Form Data
data() {
return {
form: {
experience: [{
employerName: '',
department: '',
from: null,
to: null,
tillDate: false,
type: null,
noOfYears: null,
noOfMonths: null,
other: null,
}],
name: '',
email: '',
phone: null,
course: null,
Vuelidate validation rules
validations: {
form: {
experience: {
$each: {
type: {
requiredIf: requiredIf(function() {
return this.openExperience;
}),
},
other: {
requiredIf: requiredIf((obj) => obj.type === 'Other'),
},
noOfMonths: {
minValue: minValue(0),
maxValue: maxValue(11),
},
noOfYears: {
minValue: minValue(0),
},
},
},
name: {
required,
},
email: {
email,
},
phone:{
numeric
},
dateOfBirth: {
maxValue(val){
return this.$dateFns.sub(new Date(),{years: 18}) > new Date(val);
}
},
},
},
Function to add formArray
addExperience(){
this.form.experience.push({
employerName: '',
department: '',
from: null,
to: null,
tillDate: false,
type: null,
noOfYears: null,
noOfMonths: null,
other: null,
});
const length = 'experience' + (this.form.experience.length-2).toString();
document.getElementById(length).scrollIntoView();
},
I tried removing the vuelidate rules and it worked as expected. Screen Recording
I had a computed property named 'open'. In the getter for the property, I clear the entire form for a specific condition. It turns out that adding another formGroup (Array.push) to the formArray would end up invoking all the computed properties, and in turn, calling the getter for 'open' and clearing the form.
I ended up moving the code block in the computed property getter to the mounted life-cycle hook and it works fine now.

How to do Prisma runtime model validation?

In my application, I have validated the input credential at the DTO level by using class-validator. But I need runtime model validation like sequelize ORM.
In sequelize:
'use strict';
import { DataTypes, Sequelize } from 'sequelize';
function User(sequelize: Sequelize) {
const user = sequelize.define(
'User',
{
name: {
type: DataTypes.STRING,
allowNull: false
},
role: {
type: DataTypes.STRING(20),
allowNull: false
},
email: {
type: new DataTypes.STRING,
allowNull: false,
validate: {
isEmail: {
// args: true,
msg: 'Invalid email'
},
len: {
args: [1, 100] as readonly [number, number],
msg: 'Email length should be 1 to 100 characters'
},
notNull: {
// args: true,
msg: 'Email cannot be empty'
}
}
},
password: {
type: DataTypes.VIRTUAL,
allowNull: true,
},
},
{
tableName: 'users',
underscored: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
deletedAt: 'deleted_at',
paranoid: true
}
);
return user;
}
export default User;
Is there any possibility to do model validation in Prisma?
There is an open feature request for Prisma to support runtime model validation directly at the Schema level. Alternatively, you can leverage the Client Extensions to perform validation. There is an example in this blog post that shows how to perform custom runtime validation.

Getting NO_STATUS_CODE_FROM_LAMBDA error when making ssr get calls on now

I'm running a nuxt universal app on now.sh which makes an ssr get call to a https://getcockpit.com/ server somewhere else. When I open the app I get a 502 error with code "NO_STATUS_CODE_FROM_LAMBDA".
Running it locally or deploying it as a spa instead of universal app works just fine because then the calls aren't made from lambda but from my machine I guess. My webserver running the getcockpit-cms does not receive any call from now according to it's logs so the problem doesn't seem to be on that side.
The now.sh logs really don't say much to me. The only thing I found is "Process excited before completing request" but that doesn't help me either.
'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined },
request:
Writable {
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: false,
errorEmitted: false,
bufferedRequestCount: 0,
corkedRequestsFree: [Object] },
writable: true,
domain: null,
_events: { response: [Function], error: [Function] },
_eventsCount: 2,
_maxListeners: undefined,
_options:
{ protocol: 'http:',
maxRedirects: 21,
maxBodyLength: 10485760,
path: '/api/singletons/get/intro',
method: 'GET',
headers: [Object],
agent: undefined,
auth: undefined,
hostname: 'localhost',
port: '3000',
nativeProtocols: [Object],
pathname: '/api/singletons/get/intro' },
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
upgrading: false,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'GET /api/singletons/get/intro HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nx-real-ip: 5.149.20.127\r\nsec-fetch-user: ?1\r\nsec-fetch-site: none\r\nupgrade-insecure-requests: 1\r\ncache-control: no-cache\r\nx-now-trace: zrh1\r\nx-now-deployment-url: BLURRED-NOW-DEPLOYMENT-URL\r\nx-zeit-co-forwarded-for: 5.149.20.127\r\naccept-language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7\r\nx-forwarded-proto: https\r\nsec-fetch-mode: navigate\r\nx-forwarded-for: 5.149.20.127\r\nuser-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36\r\naccept-encoding: gzip, deflate\r\nx-now-id: clckl-1566116017296-db7c5240b52c\r\npragma: no-cache\r\nx-forwarded-host: BLURRED-NOW-DEPLOYMENT-URL\r\nconnection: close\r\nAuthorization: Bearer BLURRED-API-KEY\r\nHost: localhost:3000\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Object],
socketPath: undefined,
timeout: undefined,
method: 'GET',
path: '/api/singletons/get/intro',
_ended: false,
res: null,
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable: [Circular],
[Symbol(outHeadersKey)]: [Object] },
_currentUrl: 'http://localhost:3000/api/singletons/get/intro' },
response: undefined,
isAxiosError: true,
toJSON: [Function] }
END RequestId: 5153a263-0ac9-4bf5-9c7d-4422783386ba
REPORT RequestId: 5153a263-0ac9-4bf5-9c7d-4422783386ba Duration: 234.13 ms Billed Duration: 300 ms Memory Size: 3008 MB Max Memory Used: 97 MB
RequestId: 5153a263-0ac9-4bf5-9c7d-4422783386ba Process exited before completing request
START RequestId: f32bcba9-aea6-46d0-9269-c0544a211fff Version: $LATEST
2019-08-18T08:13:39.117Z f32bcba9-aea6-46d0-9269-c0544a211fff λ Cold start took: 339.379719ms
END RequestId: f32bcba9-aea6-46d0-9269-c0544a211fff
REPORT RequestId: f32bcba9-aea6-46d0-9269-c0544a211fff Duration: 115.83 ms Billed Duration: 200 ms Memory Size: 3008 MB Max Memory Used: 53 MB
I would expect now.sh or rather lambda to make the call and ssr my app.

More extensive mangling terser-webpack-plugin?

Is there a way to thoroughly mangle vue components that have been bundled with webpack?
When applying mangling via terser-webpack-plugin with mangle.properties set to true, then not all of the property names are mangled, for example:
location: {
lng: -.134281,
lat:51.513508,
zoom:13,
pitch:1,
bearing:60
}
becomes
location:{
k:-.134281,
M:51.513508,
zoom:13,
pitch:1,
V:60
}
Edit
As requested: the relevant portion of the Webpack configuration file, in this case the default vie-cli config with the mangle.properties item manually added:
minimizer: [
{
options: {
test: /\.m?js(\?.*)?$/i,
chunkFilter: () => true,
warningsFilter: () => true,
extractComments: false,
sourceMap: false,
cache: true,
cacheKeys: defaultCacheKeys => defaultCacheKeys,
parallel: true,
include: undefined,
exclude: undefined,
minify: undefined,
terserOptions: {
output: {
comments: /^\**!|#preserve|#license|#cc_on/i
},
compress: {
arrows: false,
collapse_vars: false,
comparisons: false,
computed_props: false,
hoist_funs: false,
hoist_props: false,
hoist_vars: false,
inline: false,
loops: false,
negate_iife: false,
properties: false,
reduce_funcs: false,
reduce_vars: false,
switches: false,
toplevel: false,
typeofs: false,
booleans: true,
if_return: true,
sequences: true,
unused: true,
conditionals: true,
dead_code: true,
evaluate: true
},
mangle: {
safari10: true,
properties: true
}
}
}
}
],
These two properties (zoom, pitch) so happened to be included in the reserved name list, have a look at this default domprops.json file which UglifyJS uses internally during mangling.
A default exclusion file is provided in tools/domprops.json which should cover most standard JS and DOM properties defined in various browsers. Pass --mangle-props domprops to disable this feature
If you like to keep this default list, you could do any of the following in the custom minify option of the plugin:
Create your custom reserved name list,
Load up the default list (domprops.json) and pass in a function/filter for removing those unwanted names,
Simply merge these two files if you are sure there is no name conflict.
webpack.config.js
{
optimization: {
minimizer: [
new TerserPlugin({
minify(file, sourceMap) {
const uglifyJsOptions = {
mangle: {
properties: {
reserved: require('your_custom_list')
}
// Or filter them
properties: {
reserved: require('uglify-js/tools/domprops.json')
.filter(name => ![
'zoom',
'pitch'
]
.includes(name))
}
}
};
return require('uglify-js').minify(file, uglifyJsOptions);
},
}),
],
},
}
Also, please mind the similarities between mangle.reserved and mangle.properties.reserved while doing this, as the latter one might be what you need here. Check out the minify option structure.

How to get the name of a request via Nock object

At the point in my test code where I check assert that all nocks have been called, I have a semi-useful error message to dumps out if a nock wasn't called (since the default error message is useless):
try {
assertions(data, result);
if (assertNock !== null) {
// Expect that all mocked calls were made
if (nock.isDone() !== !!assertNock) {
console.error('One or more of your Nock matchers was never called.');
}
expect(nock.isDone()).toBe(!!assertNock);
}
done();
} catch (err) {
...
}
However, I'd like to be able to specify which call wasn't made. But, I can't seem to find a way to get that information from the nock object, which looks like:
{ [Function: startScope]
emitter:
EventEmitter {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined },
define: [Function: define],
loadDefs: [Function: loadDefs],
load: [Function: load],
enableNetConnect: [Function: enableNetConnect],
disableNetConnect: [Function: disableNetConnect],
removeInterceptor: [Function: removeInterceptor],
activeMocks: [Function: activeMocks],
pendingMocks: [Function: pendingMocks],
isDone: [Function: isDone],
isActive: [Function: isActive],
activate: [Function: activate],
cleanAll: [Function: cleanAll],
recorder:
{ rec: [Function: record],
clear: [Function: clear],
play: [Function] },
back: { [Function: Back] setMode: [Function], fixtures: null, currentMode: 'dryrun' },
restore: [Function: restore]
}
How can I get useful/identifying information about the request that was't made from the nock object?
As per the documentation, interceptors are removed once they have been called. With that knowledge, one can then use nock.activeMocks() which will return an array of items that are still active. If you have added .persist() to any of the nocks they will still be in the list. In that case you may want to use nock.pendingMocks() which will only return the nocks that haven't yet been called.
nock.activeMocks(); // [ 'GET https://www.example.com:443/fake/url', 'POST https://sts.amazonaws.com:443/' ]
nock.pendingMocks(); // [ 'GET https://www.example.com:443/fake/url' ]