Pass an already existing Model to next in Loopback - express

There is Project model
{
"name": "Project",
"plural": "Projects",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"title": {
"type": "string",
"required": true
},
"description": {
"type": "string"
},
"code": {
"type": "string"
},
"startDate": {
"type": "date",
"required": true
},
"endDate": {
"type": "date"
},
"value": {
"type": "number"
},
"infoEN": {
"type": "string"
},
"infoRU": {
"type": "string"
},
"infoAM": {
"type": "string"
},
"externalLinks": {
"type": [
"string"
]
}
},
"validations": [],
"relations": {
"industry": {
"type": "belongsTo",
"model": "Industry",
"foreignKey": "",
"options": {
"nestRemoting": true
}
},
"service": {
"type": "belongsTo",
"model": "Service",
"foreignKey": "",
"options": {
"nestRemoting": true
}
},
"tags": {
"type": "hasAndBelongsToMany",
"model": "Tag",
"foreignKey": "",
"options": {
"nestRemoting": true
}
}
},
"acls": [],
"methods": {}
}
And it hasAndBelongsToMany tags
here is Tag model
{
"name": "Tag",
"plural": "Tags",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
Now when the relation is created loopback api gives this api endpoint.
POST /Projects/{id}/tags
This creates a new tag into the tags collection and adds it to the project.
But what about adding an already existing tag to the project?
So I figured maybe I add before save hook to the Tag
Here I'll check if the tag exists and then pass the existing one for the relation.
Something like this.
tag.js
'use strict';
module.exports = function(Tag) {
Tag.observe('before save', function(ctx, next) {
console.log(ctx.instance);
Tag.find({name: ctx.instance.name})
next();
});
// Tag.validatesUniquenessOf('name', {message: 'name is not unique'});
};

#HaykSafaryan it just demo to show you how to use tag inside project
var app = require('../../server/server');
module.exports = function(project) {
var tag=app.models.tags
//afterremote it just demo. you can use any method
project.afterRemote('create', function(ctx, next) {
tag.find({name: ctx.instance.name},function(err,result)){
if(err) throw err;
next()
}
});
};
this is just example code to show you how to use update,create ,find ,upsertwithwhere etc. tag for validation you have to setup condition over here it will not take validation which you defined in tags models

Related

How to set Datatype in Additional Column in ADF

I need to set datatype for Additional Column with Dynamic Content in Sink in ADF
By default its taking nvarchar(max) from Json obj but I need bigInt
Below is a Json Obj which create table with Additional column
{
"source": {
"type": "SqlServerSource",
"additionalColumns": [
{
"name": "ApplicationId",
"value": 3604509277250831000
}
],
"sqlReaderQuery": "SELECT * from Table A",
"queryTimeout": "02:00:00",
"isolationLevel": "ReadUncommitted",
"partitionOption": "None"
},
"sink": {
"type": "AzureSqlSink",
"writeBehavior": "insert",
"sqlWriterUseTableLock": false,
"tableOption": "autoCreate",
"disableMetricsCollection": false
},
"enableStaging": false,
"translator": {
"type": "TabularTranslator",
"typeConversion": true,
"typeConversionSettings": {
"allowDataTruncation": true,
"treatBooleanAsNumber": false
}
}
}
ADF Configuration
After create table Database - column with datatype
If I convert Dynamic content into Int
#int(pipeline().parameters.application.applicationId)
Then getting below warning
Please let me know how can I set Datatype in ADF
I also tried the same and getting same result.
By default its taking nvarchar(max) from Json obj but I need bigInt
To resolve this when you add additional column in your source data set and in Mapping click onimport schema it will import the schema of the source and also give you additional column in schema you have to change the type of the column as Int64 as shown in below image. in below image you can see after name there is additional means it is an additional column.
After this run your pipeline, It will create additional column with data type bigint .
{
"name": "pipeline2",
"properties": {
"activities": [
{
"name": "Copy data1",
"type": "Copy",
"dependsOn": [],
"policy": {
"timeout": "0.12:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"userProperties": [],
"typeProperties": {
"source": {
"type": "JsonSource",
"additionalColumns": [
{
"name": "name",
"value": {
"value": "#pipeline().parameters.demo.age",
"type": "Expression"
}
}
],
"storeSettings": {
"type": "AzureBlobFSReadSettings",
"recursive": true,
"enablePartitionDiscovery": false
},
"formatSettings": {
"type": "JsonReadSettings"
}
},
"sink": {
"type": "AzureSqlSink",
"writeBehavior": "insert",
"sqlWriterUseTableLock": false,
"tableOption": "autoCreate",
"disableMetricsCollection": false
},
"enableStaging": false,
"translator": {
"type": "TabularTranslator",
"mappings": [
{
"source": {
"path": "$['taskId']"
},
"sink": {
"name": "taskId",
"type": "String"
}
},
{
"source": {
"path": "$['taskObtainedScore']"
},
"sink": {
"name": "taskObtainedScore",
"type": "String"
}
},
{
"source": {
"path": "$['multiInstance']"
},
"sink": {
"name": "multiInstance",
"type": "String"
}
},
{
"source": {
"path": "$['name']"
},
"sink": {
"name": "name",
"type": "Int64"
}
}
],
"collectionReference": ""
}
},
"inputs": [
{
"referenceName": "Json1",
"type": "DatasetReference"
}
],
"outputs": [
{
"referenceName": "AzureSqlTable1",
"type": "DatasetReference"
}
]
}
],
"parameters": {
"demo": {
"type": "object",
"defaultValue": {
"name": "John",
"age": 30,
"isStudent": true
}
}
},
"annotations": []
}
}
OUTPUT:

JSON Schema - How to narrow down possible array object values

How can the following requirements be configured in a JSON schema.
I have the following JSON
{
"orderMethods": [
{
"requestType": "some service",
"deployType": "MANUAL",
"deployLabel": "some label"
},
{
"requestType": "some service",
"deployType": "MANUAL",
"deployLabel": "some label"
},
{
"requestType": "some service",
"deployType": "AUTO",
"deploySubType": "REST",
"deployLabel": "some label",
"deployConfig": "some config"
},
{
"requestType": "some service",
"deployType": "AUTO",
"deploySubType": "DB",
"deployLabel": "some label",
"deployConfig": "some config"
}
]
}
Requirements:
only one deployType = "MANUAL" is allowed
only one deployType = "AUTO" is allowed
additionally, only one deploySubType = "REST or "DB" is allowed
Currently I have the following JSON schema. Unfortunately the above JSON is valid. How can the above requirements be addressed?
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"orderMethods": {
"$ref": "#/definitions/OrderMethods"
}
},
"additionalProperties": false,
"definitions": {
"OrderMethods": {
"type": "array",
"items": {
"$ref": "#/definitions/OrderMethod"
}
},
"OrderMethod": {
"oneOf": [
{
"$ref": "#/definitions/OrderMethodManualDeploy"
},
{
"$ref": "#/definitions/OrderMethodAutoDeploy"
}
],
"uniqueItems": true
},
"OrderMethodAutoDeploy": {
"oneOf": [
{
"$ref": "#/definitions/OrderMethodAutoRestDeploy"
},
{
"$ref": "#/definitions/OrderMethodAutoDBDeploy"
}
],
"uniqueItems": true
},
"OrderMethodManualDeploy": {
"type": "object",
"properties": {
"requestType": {
"type": "string"
},
"deployType": {
"const": "MANUAL"
},
"deployLabel": {
"type": "string"
}
},
"required": [
"requestType",
"deployType",
"deployLabel"
],
"additionalProperties": false
},
"OrderMethodAutoRestDeploy": {
"type": "object",
"properties": {
"requestType": {
"type": "string"
},
"deployType": {
"const": "AUTO"
},
"deploySubType": {
"const": "REST"
},
"deployLabel": {
"type": "string"
},
"deployConfig": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"requestType",
"deployType",
"deploySubType",
"deployLabel",
"deployConfig"
]
},
"OrderMethodAutoDBDeploy": {
"type": "object",
"properties": {
"requestType": {
"type": "string"
},
"deployType": {
"const": "AUTO"
},
"deploySubType": {
"const": "DB"
},
"deployConfig": {
"type": "string"
},
"deployLabel": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"requestType",
"deployType",
"deploySubType",
"deployLabel",
"deployConfig"
]
}
}
}
Thanks for your help/ideas.

Why oneOf does not work on my schema in jsonschema?

My login has different payloads one is:
{
"username": "",
"pass": ""
}
And one of the other is:
{
"username": "",
"pass": "",
"facebook": true
}
And the last:
{
"username": "",
"pass": "",
"google": true
}
My schema is as follow:
login_schema = {
"title": "UserLogin",
"description": "User login with facebook, google or regular login.",
"type": "object",
"properties": {
"username": {
"type": "string"
},
"pass": {
"type": "string"
},
"facebook": {
"type": "string"
},
"google": {
"type": "string"
}
},
"oneOf": [
{
"required": [
"username",
"pass"
],
"additionalProperties": False,
},
{
"required": [
"username",
"pass"
"google"
]
},
{
"required": [
"username",
"pass",
"facebook"
]
}
],
"minProperties": 2,
"additionalProperties": False,
}
It should give an error for the below sample:
{
"username": "",
"pass": "",
"google": "",
"facebook": ""
}
But it validates the schema successfully! What I have done wrong in the above schema?
EDIT-1:
pip3 show jsonschema
Name: jsonschema
Version: 3.0.2
Summary: An implementation of JSON Schema validation for Python
Home-page: https://github.com/Julian/jsonschema
Author: Julian Berman
Author-email: Julian#GrayVines.com
License: UNKNOWN
Location: /usr/local/lib/python3.7/site-packages
Requires: setuptools, six, attrs, pyrsistent
EDIT-2:
What I get as an error is:
jsonschema.exceptions.ValidationError: {'username': '', 'pass': '', 'google': '12'} is valid under each of {'required': ['username', 'pass', 'google']}, {'required': ['username', 'pass']}
A live demo of the error: https://jsonschema.dev/s/mXg5X
Your solution is really close. You just need to change /oneOf/0 to
{
"properties": {
"username": true,
"pass": true
},
"required": ["username", "pass"],
"additionalProperties": false
}
The problem is that additionalProperties doesn't consider the required keyword when determining what properties are considered "additional". It considers only properties and patternProperties. When just using required, additionalProperties considers all properties to be "additional" and the only valid value is {}.
However, I suggest a different approach. The dependencies keyword is useful in these situations.
{
"type": "object",
"properties": {
"username": { "type": "string" },
"pass": { "type": "string" },
"facebook": { "type": "boolean" },
"google": { "type": "boolean" }
},
"required": ["username", "pass"],
"dependencies": {
"facebook": { "not": { "required": ["google"] } },
"google": { "not": { "required": ["facebook"] } }
},
"additionalProperties": false
}

LoopbackJS - Tokens for user invites

I'm using loopback as the API server for my application. I'm building a social like network, where it's required to invite users via email. In order to associate the invitee with the inviter, I want the inviter to create a 'request token' associated with his userId, which then is sent via email in a format like this: domain.com/register?token=XXXXXX
The built-in Access Token model seems perfect for this purpose as a base model used so the idea is to create a new model "RequestToken" inheriting from the AccessToken model, however, the new model is then used for authentication purposes as well, which I don't want.
Following are my config files. It's worth mentioning that the below seen "Customer" model is extending Loopbacks "User" Model.
/server/model-config.json:
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../node_modules/loopback-ds-timestamp-mixin",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db",
"public": false
},
"AccessToken": {
"dataSource": "db",
"public": false,
"relations": {
"user": {
"type": "belongsTo",
"model": "Customer",
"foreignKey": "userId"
}
}
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false,
"options": {
"strictObjectIDCoercion": true
}
},
"Role": {
"dataSource": "db",
"public": false
},
"Email": {
"dataSource": "mail",
"public": false
},
"Customer": {
"dataSource": "db",
"public": true
},
"Friend": {
"dataSource": "db",
"public": true
},
"Memory": {
"dataSource": "db",
"public": true
},
"RequestToken": {
"dataSource": "db",
"public": true
}
}
Under "Customer" I've also tried to include:
"relations": {
"accessTokens": {
"type": "hasMany",
"model": "AccessToken",
"foreignKey": "userId",
"options": {
"disableInclude": true
}
}
}
common/customer.json
{
"name": "Customer",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"mixins": {
"TimeStamp": true
},
"properties": {
"firstName": {
"type": "string",
"required": true
},
"lastName": {
"type": "string",
"required": true
},
"dob": {
"type": "date"
},
"country": {
"type": "string"
}
},
"validations": [],
"relations": {
"accessTokens": {
"type": "hasMany",
"model": "AccessToken",
"foreignKey": "userId",
"options": {
"disableInclude": true
}
},
"requestTokens": {
"type": "hasMany",
"model": "RequestToken",
"foreignKey": "userId",
"options": {
"disableInclude": true
}
}
},
"acls": [
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}
],
"methods": {}
}
common/request-token.json
{
"name": "RequestToken",
"base": "AccessToken",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {
"user": {
"type": "belongsTo",
"model": "Customer",
"foreignKey": "ownerId"
}
},
"acls": [],
"methods": {}
}
Summary:
How can I create a new "RequestToken" model, extending Loopbacks "AccessToken" model, but keep using the built-in AccessToken model for authentication etc.? Is it possible at all? As soon as I take the line '"base": "AccessToken"' out of the request-token.json file, all authentication method work again.
Thanks a lot in advance!
It seems I found a solution for this. Within server.js I needed to tell the app to use the AccessToken model.
server.js
...
app.use(loopback.token({
model: app.models.accessToken,
}));
...
I've added it just after
const app = loopback();
The docs refer to it to use it for authentication via cookies in the LB2 docs.
https://loopback.io/doc/en/lb2/Making-authenticated-requests.html
I'm using Loopback3. Within the LB3 docs, they do not mention this way anymore, so if there is another solution, happy to change the accepted answer.
Cheers

Failed to execute 'send' on 'XMLHttpRequest' for only one url in Loopback

Strongloop/Loopback node.js server used with 'ng-admin' editor and sqlite db. I need to get count of entities:
var Httpreq = new XMLHttpRequest();
Httpreq.open('GET', yourUrl, false);
Httpreq.send(null);
return Httpreq.responseText;
where yourUrl is like http://localhost:3000/api/v1/entity/count.
All urls works except one of entity named 'Advertisement', I have angular.js:12783 Error: Failed to execute 'send' on 'XMLHttpRequest': Failed to load http://localhost:3000/api/v1/advertisement/count. This url works in API explorer.
Advertisement.json:
{
"name": "Advertisement",
"base": "EntityBase",
"plural": "Advertisement",
"options": {
"validateUpsert": true,
"sqlite3": {
"table": "advertisement"
}
},
"properties": {
"name": {
"type": "string",
"required": true
},
"category_id": {
"type": "number"
},
"due_date": {
"type": "string"
},
"from_date": {
"type": "string"
},
"phone": {
"type": "string"
},
"site": {
"type": "string"
}
},
"validations": [],
"relations": {
"category": {
"type": "belongsTo",
"model": "Category",
"foreignKey": "category_id"
},
"photos": {
"type": "hasMany",
"model": "Photo",
"foreignKey": "advertisement_id"
}
},
"acls": [],
"methods": {},
"mixins": {
"Timestamp": {},
"SoftDelete": {},
"GenderAge": {},
"Descripted": {}
}
}
Renamed entity to Commercial to fix this.