Bicep Pass storage account connection string to key vault - azure-resource-manager

I have 2 resource groups as follow:
rg-shared
rg-storage-accounts
in resource group one I am trying to create a storage account and get its connection string and pass it to resourcegroup2 on which I have a key vault.
my actual code is as follow.
Shared.bicep
targetScope = 'resourceGroup'
param deploymentIdOne string = newGuid()
param deploymentIdTwo string = newGuid()
output deploymentIdOne string = '${deploymentIdOne}-${deploymentIdTwo}'
output deploymentIdTwo string = deploymentIdTwo
param keyvaultmain string = 'Name-keyvault'
param keyvaultshared string = 'Name-keyvault'
param sharedManagedIdentity string = 'Name-Managed-identity'
param storageAccountString string
var storagePrefix = 'sttesteur'
var clientDataKeyPrefix = 'Key-Data-'
var learnersguidsecrets = 'Guidtest'
param tenantCodes array = [
'tste'
]
resource keyVaultClients 'Microsoft.KeyVault/vaults#2021-06-01-preview' existing = {
name: keyvaultmain
}
resource keyVaultShared 'Microsoft.KeyVault/vaults#2021-06-01-preview' existing = {
name: keyvaultshared
}
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities#2018-11-30' = {
name: sharedManagedIdentity
location: resourceGroup().location
}
resource kvClientsKey 'Microsoft.KeyVault/vaults/keys#2021-06-01-preview' = [for code in tenantCodes: {
name: '${keyVaultClients.name}/${clientDataKeyPrefix}${toUpper(code)}'
properties: {
keySize: 2048
kty: 'RSA'
// Assign the least permission
keyOps: [
'unwrapKey'
'wrapKey'
]
}
}]
resource accessPolicy 'Microsoft.KeyVault/vaults/accessPolicies#2021-06-01-preview' = {
name: '${keyVaultClients.name}/add'
properties: {
accessPolicies: [
{
tenantId: subscription().tenantId
objectId: managedIdentity.properties.principalId
permissions: {
// minimum required permission
keys: [
'get'
'unwrapKey'
'wrapKey'
]
}
}
]
}
}
resource clientLearnersGuid 'Microsoft.KeyVault/vaults/secrets#2021-06-01-preview' = [for tenant in tenantCodes: {
name: '${keyVaultClients.name}/${tenant}${learnersguidsecrets}'
properties: {
contentType: 'GUID Key'
value: '${deploymentIdOne}-${deploymentIdTwo}'
}
}]
resource storageAccountConnectionString 'Microsoft.KeyVault/vaults/secrets#2021-06-01-preview' = [for tenant in tenantCodes: {
name: '${keyVaultShared.name}${storagePrefix}${tenant}'
properties:{
contentType: '${tenant} Storage Account Connection String'
value: storageAccountString
}
}]
And this is my storage-account.bicep
param tenantCodes array = [
'tste'
]
param tenantManagedIdentity string = 'Manage-identity-Name'
param secondresource string = 'rg-sec-eur-shared'
var keyVaultKeyPrefix = 'Key-Data-'
var storagePrefix = 'sthritesteur'
// Create a managed identity
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities#2018-11-30' = {
name: tenantManagedIdentity
location: resourceGroup().location
}
// Create storage accounts
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-04-01' = [for tenantCode in tenantCodes: {
name: '${storagePrefix}${tenantCode}'
location: resourceGroup().location
kind: 'StorageV2'
sku: {
name: 'Standard_RAGRS'
}
// Assign the identity
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${managedIdentity.id}': {}
}
}
properties: {
allowCrossTenantReplication: true
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
allowSharedKeyAccess: true
networkAcls: {
bypass: 'AzureServices'
virtualNetworkRules: []
ipRules: []
defaultAction: 'Allow'
}
supportsHttpsTrafficOnly: true
encryption: {
identity: {
// specify which identity to use
userAssignedIdentity: managedIdentity.id
}
keySource: 'Microsoft.Keyvault'
keyvaultproperties: {
keyname: '${keyVaultKeyPrefix}${toUpper(tenantCode)}'
// keyvaulturi: keyVault.properties.vaultUri
keyvaulturi:'https://keyvaultclient.vault.azure.net'
}
services: {
file: {
keyType: 'Account'
enabled: true
}
blob: {
keyType: 'Account'
enabled: true
}
}
}
accessTier: 'Hot'
}
}]
resource storage_Accounts_name_default 'Microsoft.Storage/storageAccounts/blobServices#2021-04-01' = [ for (storageName, i) in tenantCodes :{
parent: storageAccount[i]
name: 'default'
properties: {
changeFeed: {
enabled: false
}
restorePolicy: {
enabled: false
}
containerDeleteRetentionPolicy: {
enabled: true
days: 7
}
cors: {
corsRules: []
}
deleteRetentionPolicy: {
enabled: true
days: 30
}
isVersioningEnabled: true
}
}]
module connectionString 'shared.bicep' = [for (storageName, i) in tenantCodes :{
scope: resourceGroup(secondresource)
name: storageName
params: {
storageAccountString: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount[i].name};AccountKey=${listKeys(storageAccount[i].id, storageAccount[i].apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
}
}]
This is the details of this workflow.
in the resource group rg-sharedi have 2 key vaults, keyvault-sharedand keyvaultstorage. And their purpose is as follow:
keyvault-shared => Store StorageAccount Connection String as Secret
keyvault-storage => Generate a Key Name based on the `tenantCode` in the key section, and in secret, generate a GUID and store it
while in the other resource-group rg-storage I want to create a storage account, encrypt the storage account with the key I have generated in the keyault earlier, and pass the connection string of this storageAccount to the shared key vault.
Following your advice, I used the module from shared.bicep and called it in my storage account.bicep.
Based on my command:
az deployment group what-if -f ./storage-account.bicep -g rg-storage-accounts
the output It shows that will create only the resource in the storage-account.bicep:
user identity
storageAccount
container
How to reproduce:
Create 2 resource groups (shared and storage accounts)
in Shared create 2 key vaults
Update the bicep files with the correct key vault names.
In both bicep scripts in tenantCode put a random name to create a storage account or multiple storage accounts.
and run the above bicep command.
I tried to explain as clear as I could this issue, as its driving me crazy and have no idea what I am doing wrong and this stage.
Please please, if you need anymore information about this issue, just ask and will be glad to clarify any doubt
UPDATE:
To generate the key before hand, I moved the key creation into the storage.bicep as follow:
resource keyVaultClients 'Microsoft.KeyVault/vaults#2021-06-01-preview' existing = {
name: keyvaultmain
scope: resourceGroup(secondresource)
}
resource kvClientsKey 'Microsoft.KeyVault/vaults/keys#2021-06-01-preview' = [for code in tenantCodes: {
name: '${keyVaultClients.name}-${clientDataKeyPrefix}${toUpper(code)}'
properties: {
keySize: 2048
kty: 'RSA'
// Assign the least permission
keyOps: [
'unwrapKey'
'wrapKey'
]
}
}]
but I get this error:
{"error":{"code":"InvalidTemplate","message":"Deployment template validation failed: 'The template resource 'keyvault-Key-Data-ORNX' for type 'Microsoft.KeyVault/vaults/keys' at line '54' and column '46' has incorrect segment lengths. A nested resource type must have identical number of segments as its resource name. A root resource type must have segment length one greater than its resource name. Please see https://aka.ms/arm-template/#resources for usage details.'.","additionalInfo":[{"type":"TemplateViolation","info":{"lineNumber":54,"linePosition":46,"path":"properties.template.resources[1].type"}}]}}
Which I don't understand exactly to what refers.
UPDATE:
This is an interesting output. So according to the last update (and thank you so so much for your help) I realised that at the code is creating all the correct resource, but at the very end it throws this error:
{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"Conflict","message":"{\r\n \"status\": \"Failed\",\r\n \"error\": {\r\n \"code\": \"ResourceDeploymentFailure\",\r\n \"message\": \"The resource operation completed with terminal provisioning state 'Failed'.\",\r\n \"details\": [\r\n {\r\n \"code\": \"DeploymentFailed\",\r\n \"message\": \"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.\",\r\n \"details\": [\r\n {\r\n \"code\": \"Conflict\",\r\n \"message\": \"{\\r\\n \\\"error\\\": {\\r\\n \\\"code\\\": \\\"StorageAccountOperationInProgress\\\",\\r\\n \\\"message\\\": \\\"An operation is currently performing on this storage account that requires exclusive access.\\\"\\r\\n }\\r\\n}\"\r\n },\r\n {\r\n \"code\": \"Conflict\",\r\n \"message\": \"{\\r\\n \\\"error\\\": {\\r\\n \\\"code\\\": \\\"StorageAccountOperationInProgress\\\",\\r\\n \\\"message\\\": \\\"An operation is currently performing on this storage account that requires exclusive access.\\\"\\r\\n }\\r\\n}\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n}"}]}}

For testing , I used nested template module for creating a single Storage account and then stored the connection string in the key vault present in the another resource group.
Scenario:
Keyvaultclient.bicep>>nested(storage.bicep)>>nested(shared.bicep)
Code:
Keyvaultclient.bicep:
param deploymentIdOne string = newGuid()
param deploymentIdTwo string = newGuid()
output deploymentIdOne string = '${deploymentIdOne}-${deploymentIdTwo}'
output deploymentIdTwo string = deploymentIdTwo
param storagerg string = 'rgnamewherestorageaccountistobecreated'
param sharedManagedIdentity string = 'identityforkeyvault'
param keyvaultmain string = 'keyvaultclienttes1234'
param tenantCodes array = [
'tste'
]
var clientDataKeyPrefix = 'Key-Data-'
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities#2018-11-30' = {
name: sharedManagedIdentity
location: resourceGroup().location
}
resource keyVaultClients 'Microsoft.KeyVault/vaults#2021-06-01-preview' existing = {
name: keyvaultmain
}
resource kvClientsKey 'Microsoft.KeyVault/vaults/keys#2021-06-01-preview' = [for code in tenantCodes: {
parent:keyVaultClients
name: '${keyVaultClients.name}-${clientDataKeyPrefix}${toUpper(code)}'
properties: {
keySize: 2048
kty: 'RSA'
// Assign the least permission
keyOps: [
'unwrapKey'
'wrapKey'
]
}
}]
resource accessPolicy 'Microsoft.KeyVault/vaults/accessPolicies#2021-06-01-preview' = {
parent:keyVaultClients
name: 'add'
properties: {
accessPolicies: [
{
tenantId: subscription().tenantId
objectId: managedIdentity.properties.principalId
permissions: {
// minimum required permission
keys: [
'get'
'unwrapKey'
'wrapKey'
]
}
}
]
}
}
resource clientLearnersGuid 'Microsoft.KeyVault/vaults/secrets#2021-06-01-preview' = [for tenant in tenantCodes: {
parent:keyVaultClients
name: '${keyVaultClients.name}${tenant}'
properties: {
contentType: 'GUID Key'
value: '${deploymentIdOne}-${deploymentIdTwo}'
}
dependsOn:kvClientsKey
}]
module StorageAccount './storage.bicep' = [for (storageName, i) in tenantCodes :{
scope: resourceGroup(storagerg)
name: storageName
params: {
ManagedIdentityid:managedIdentity.id
kvname:keyVaultClients.name
uri:keyVaultClients.properties.vaultUri
}
dependsOn:clientLearnersGuid
}]
Storage.bicep:
param tenantCodes array = [
'tste'
]
param ManagedIdentityid string
param uri string
param kvname string
param keyvaultrg string = 'rgwherethekeyvaultsarepresent'
var keyVaultKeyPrefix = 'Key-Data-'
var storagePrefix = 'sthritesteur'
// Create storage accounts
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-04-01' = [for tenantCode in tenantCodes: {
name: '${storagePrefix}${tenantCode}'
location: resourceGroup().location
kind: 'StorageV2'
sku: {
name: 'Standard_RAGRS'
}
// Assign the identity
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${ManagedIdentityid}':{}
}
}
properties: {
allowCrossTenantReplication: true
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
allowSharedKeyAccess: true
networkAcls: {
bypass: 'AzureServices'
virtualNetworkRules: []
ipRules: []
defaultAction: 'Allow'
}
supportsHttpsTrafficOnly: true
encryption: {
identity: {
// specify which identity to use
userAssignedIdentity: ManagedIdentityid
}
keySource: 'Microsoft.Keyvault'
keyvaultproperties: {
keyname: '${kvname}-${keyVaultKeyPrefix}${toUpper(tenantCode)}'
keyvaulturi:uri
}
services: {
file: {
keyType: 'Account'
enabled: true
}
blob: {
keyType: 'Account'
enabled: true
}
}
}
accessTier: 'Hot'
}
}]
resource storage_Accounts_name_default 'Microsoft.Storage/storageAccounts/blobServices#2021-04-01' = [ for (storageName, i) in tenantCodes :{
parent: storageAccount[i]
name: 'default'
properties: {
changeFeed: {
enabled: false
}
restorePolicy: {
enabled: false
}
containerDeleteRetentionPolicy: {
enabled: true
days: 7
}
cors: {
corsRules: []
}
deleteRetentionPolicy: {
enabled: true
days: 30
}
isVersioningEnabled: true
}
}]
module connectionString './shared.bicep' = [for (storageName, i) in tenantCodes :{
scope: resourceGroup(keyvaultrg)
name: storageName
params: {
storageAccountString: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount[i].name};AccountKey=${listKeys(storageAccount[i].id, storageAccount[i].apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
}
}]
shared.bicep:
param keyvaultshared string = 'keyvaultsharedtest12345'
param storageAccountString string
param tenantCodes array = [
'tste'
]
resource keyVaultShared 'Microsoft.KeyVault/vaults#2021-06-01-preview' existing = {
name: keyvaultshared
}
resource storageAccountConnectionString 'Microsoft.KeyVault/vaults/secrets#2021-06-01-preview' = [for tenant in tenantCodes: {
parent:keyVaultShared
name: '${keyVaultShared.name}-test${tenant}'
properties:{
contentType: '${tenant} Storage Account Connection String'
value: storageAccountString
}
}]
Output:
keyvaultclient.bicep will be deployed to the kvresourcegroup:
az deployment group create -n TestDeployment -g keyvaultrg --template-file "path\to\keyvaultclient.bicep"

Related

Argument userId: Got invalid value '5106220' on Prisma.findManyTodos. Provided String, expected IntFilter or Int:

using next.js +next-auth + Prisma + PostgreSQL
I added a custom login page and added the providers as well.
my userId in the database is Int so when I log in with credentials I have no issue but when logging in with one of the social providers I get an error...
Argument userId: Got invalid value '5106220' on Prisma.findManyTodos. Provided String, expected IntFilter or Int:
how to force providers to use Int instead of String when connecting to a database.
This error occurs whenever i need to connect the database
This is a Full error
provider: {
id: 'facebook',
name: 'Facebook',
type: 'oauth',
authorization: {
url: 'https://www.facebook.com/v11.0/dialog/oauth',
params: [Object]
},
token: {
url: 'https://graph.facebook.com/oauth/access_token',
params: {}
},
userinfo: {
url: 'https://graph.facebook.com/me',
params: [Object],
request: [AsyncFunction: request]
},
profile: [Function: profile],
idToken: false,
checks: [ 'state' ],
clientId: 'MyClientId',
clientSecret: '413db228b5b8e2e1134f5',
signinUrl: 'http://localhost:3000/api/auth/signin/facebook',
callbackUrl: 'http://localhost:3000/api/auth/callback/facebook'
}
}
[next-auth][debug][PROFILE_DATA] {
OAuthProfile: {
id: '11062270',
name: 'obi ',
email: 'ow1#gmail.com',
picture: { data: [Object] }
}
}
[next-auth][debug][OAUTH_CALLBACK_RESPONSE] {
profile: {
id: '5062260',
name: ' Eco',
email: 'ow1#gmail.com',
image: 'https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=570&height=50&width=50&e&hash=AeR6hTT03RbzF9Z9hkg'
},
account: {
provider: 'facebook',
type: 'oauth',
providerAccountId: '0711062270',
access_token: 'EAAVmjxtUcOMBACPeAQm3Ocb0zzKcl8uiZAnZCYhhYxGo',
token_type: 'bearer',
expires_at: 1669548134
},
OAuthProfile: {
id: '560',
name: 'co',
email: 'ow1#gmail.com',
picture: { data: [Object] }
}
}
{
user: {
name: 'co',
email: 'ow1#gmail.com',
image: 'https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=5007110622680570&height=50&width=50&ext=1666977090&hash=AeR6hTT03RbzF9Z9hkg',
id: '106226'
},
expires: '2022-10-28T17:11:31.515Z',
id: '1062'
}
PrismaClientValidationError:
Invalid `prisma.todos.findMany()` invocation:
{
where: {
userId: '7110620'
~~~~~~~~~~~~~~~~~~
},
select: {
id: true,
text: true,
done: true
}
}
Argument userId: Got invalid value '5106220' on prisma.findManyTodos. Provided String, expected IntFilter or Int:
type IntFilter {
equals?: Int
in?: List<Int>
notIn?: List<Int>
lt?: Int
lte?: Int
gt?: Int
gte?: Int
not?: Int | NestedIntFilter
}
type IntFilter {
equals?: Int
in?: List<Int>
notIn?: List<Int>
lt?: Int
lte?: Int
gt?: Int
gte?: Int
not?: Int | NestedIntFilter
}
at Document.validate (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:29297:20)
at serializationFn (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:31876:19)
at runInChildSpan (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:25100:12)
at PrismaClient._executeRequest (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:31883:31)
at consumer (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:31810:23)
at C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:31815:51
at AsyncResource.runInAsyncScope (node:async_hooks:201:9)
at C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:31815:29
at runInChildSpan (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:25100:12)
at PrismaClient._request (C:\Users\elear\Desktop\TokTok4u\node_modules\#prisma\client\runtime\index.js:31812:22) {
clientVersion: '4.4.0'
}
API resolved without sending a response for /api/v1/todo/get, this may result in stalled requests.
According to the Prisma adapter in the NextAuth docs, the User model in the Prisma schema needs to have an id field with a String type.
You must add + before the field.
Example +id or +productId and try again.
This helps me resolve my problem.

Azure Bicep template deployment failure with error: "The value of parameter linuxConfiguration.ssh.publicKeys.path is invalid.\"

I created a bicep templated to deploy on Azure (using bash) a linux vm with the associated resources (nic, vnet, subnet, publicIP). Part of the deployment fails; where all the associated resources are deployed but the vm itself fails to deploy.
The error is as follows:
{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"BadRequest","message":"{\r\n "error": {\r\n "code": "InvalidParameter",\r\n "message": "Destination path for SSH public keys is currently limited to its default value /home/user/.ssh/authorized_keys due to a known issue in Linux provisioning agent.",\r\n "target": "linuxConfiguration.ssh.publicKeys.path"\r\n }\r\n}"}]}}
The bicep template provided by microsoft uses the path: '/home/${adminUsername}/.ssh/authorized_keys'
I can't seem to figure out a way for it to deploy. Any assistance would greatly appreciated.
Here is the bicep file that causes the error:
#description('Name of the VM')
param vmName string = 'stagingLinuxVM'
#description('location for all resources')
param location string = resourceGroup().location
#description('vm sizes allowed RAM & temp storage in GiB per tier (respectively): 0.5/4; 1/4; 2/4; 4/8; 8/16')
#allowed([
'Standard_B1s'
'Standard_B1ms'
'Standard_B2s'
'Standard_B2ms'
])
param vmSize string = 'Standard_B1s'
#description('Username for the VM')
param adminUsername string
#description('SSH Key for the Virtual Machine')
#secure()
param adminPasswordKey string
#description('name of VNET')
param virtualNetworkName string = 'vnet'
#description('name of the subnet in the virtual network')
param subnetName string = 'Subnet'
param dnsLabelPrefix string = toLower('${vmName}-${uniqueString(resourceGroup().id)}')
var osDiskType = 'Standard_LRS'
var networkInterfaceName = '${vmName}nic'
var addressPrefix = '10.1.0.0/16'
var publicIPAddressName = '${vmName}PublicIP'
var subnetAddressPrefix = '10.1.0.0/24'
var linuxConfiguration = {
disablePasswordAuthentication: true
provisionVMAgent: true
ssh: {
publicKeys: [
{
path: '/home/${adminUsername}/.ssh/authorized_keys'
keyData: adminPasswordKey
}
]
}
}
resource nic 'Microsoft.Network/networkInterfaces#2021-08-01' = {
name: networkInterfaceName
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: subnet.id
}
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: publicIP.id
}
}
}
]
}
}
resource vnet 'Microsoft.Network/virtualNetworks#2021-08-01' = {
name: virtualNetworkName
location: location
properties: {
addressSpace: {
addressPrefixes: [
addressPrefix
]
}
}
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets#2021-08-01' = {
parent: vnet
name: subnetName
properties: {
addressPrefix: subnetAddressPrefix
privateEndpointNetworkPolicies: 'Enabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
}
resource publicIP 'Microsoft.Network/publicIPAddresses#2021-08-01' = {
name: publicIPAddressName
location: location
sku: {
name: 'Basic'
}
properties: {
publicIPAllocationMethod: 'Dynamic'
publicIPAddressVersion: 'IPv4'
dnsSettings: {
domainNameLabel: dnsLabelPrefix
}
idleTimeoutInMinutes: 4
}
}
resource vm 'Microsoft.Compute/virtualMachines#2021-11-01' = {
name: vmName
location: location
properties: {
hardwareProfile: {
vmSize: vmSize
}
osProfile: {
adminPassword: adminPasswordKey
adminUsername: adminUsername
computerName: vmName
linuxConfiguration: linuxConfiguration
}
storageProfile: {
imageReference: {
offer: 'UbuntuServer'
publisher: 'Canonical'
sku: '18.04-LTS'
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
deleteOption: 'Delete'
diskSizeGB: 32
osType: 'Linux'
managedDisk: {
storageAccountType: osDiskType
}
}
}
networkProfile: {
networkInterfaces: [
{
id: nic.id
}
]
}
}
}
output adminUsername string = adminUsername
output hostname string = publicIP.properties.dnsSettings.fqdn
output sshComand string = 'ssh ${adminUsername}#${publicIP.properties.dnsSettings.fqdn}'

Apollo/GraphQL: Setting Up Resolver for String Fields?

In GraphiQL at http://localhost:8080/graphiql, I'm using this query:
{
instant_message(fromID: "1"){
fromID
toID
msgText
}
}
I'm getting this response:
{
"data": {
"instant_message": {
"fromID": null,
"toID": null,
"msgText": null
}
},
"errors": [
{
"message": "Resolve function for \"instant_message.fromID\" returned undefined",
"locations": [
{
"line": 3,
"column": 5
}
]
},
{
"message": "Resolve function for \"instant_message.toID\" returned undefined",
"locations": [
{
"line": 4,
"column": 5
}
]
},
{
"message": "Resolve function for \"instant_message.msgText\" returned undefined",
"locations": [
{
"line": 5,
"column": 5
}
]
}
]
}
I tried to set up my system according to the examples found here:
https://medium.com/apollo-stack/tutorial-building-a-graphql-server-cddaa023c035#.s7vjgjkb7
Looking at that article, it doesn't seem to be necessary to set up individual resolvers for string fields, but I must be missing something.
What is the correct way to update my resolvers so as to return results from string fields? Example code would be greatly appreciated!
Thanks very much in advance to all for any thoughts or info.
CONNECTORS
import Sequelize from 'sequelize';
//SQL CONNECTORS
const db = new Sequelize(Meteor.settings.postgres.current_dev_system.dbname, Meteor.settings.postgres.current_dev_system.dbuser, Meteor.settings.postgres.current_dev_system.dbpsd, {
host: 'localhost',
dialect: 'postgres',
});
db
.authenticate()
.then(function(err) {
console.log('Connection to Sequelize has been established successfully.');
})
.catch(function (err) {
console.log('Unable to connect to the Sequelize database:', err);
});
const IMModel = db.define('IM', {
id: {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
fromID: {type: Sequelize.STRING},
toID: {type: Sequelize.STRING},
msgText: {type: Sequelize.STRING}
});
IMModel.sync({force: true}).then(function () {
// Table created
return IMModel.create({
fromID: '1',
toID: '2',
msgText: 'msg set up via IMModel.create'
});
});
const IM = db.models.IM;
export {db, IM };
SCHEMA
const typeDefinitions = [`
type instant_message {
id: Int
fromID: String
toID: String
msgText: String
}
type Query {
instant_message(fromID: String, toID: String, msgText: String): instant_message
}
type RootMutation {
createInstant_message(
fromID: String!
toID: String!
msgText: String!
): instant_message
}
schema {
query: Query,
mutation: RootMutation
}
`];
export default typeDefinitions;
RESOLVERS
import * as connectors from './db-connectors';
import { Kind } from 'graphql/language';
const b = 100;
const resolvers = {
Query: {
instant_message(_, args) {
const a = 100;
return connectors.IM.find({ where: args });
}
},
RootMutation: {
createInstant_message: (__, args) => { return connectors.IM.create(args); },
},
};
export default resolvers;
When you define your GraphQLObjectTypes you need to provide a resolver for each of their fields.
You defined your instant_message with multiple fields but did not provide resolvers for each of these fields.
More over you defined the types of those field with regular typescript fields while you need to define it with GraphQL types (GraphQLInt, GraphQLString, GrapQLFloat etc..)
So defining your type should look something like this:
let instant_message = new GraphQLObjectType({
id: {
type: GraphQLInt,
resolve: (instantMsg)=> {return instantMsg.id}
}
fromID: {
type: GraphQLString,
resolve: (instantMsg)=> {return instantMsg.fromID}
}
toID: {
type: GraphQLString,
resolve: (instantMsg)=> {return instantMsg.toID}
}
msgText: {
type: GraphQLString,
resolve: (instantMsg)=> {return instantMsg.msgText}
}
})
In addition, you will need to define your Query as follows:
let Query = new GraphQLObjectType({
name: "query",
description: "...",
fields: () => ({
instant_messages: {
type: new GraphQLList(instant_message),
args: {
id: {type: GraphQLInt}
},
resolve: (root, args) => {
connectors.IM.find({ where: args })
}
}
})
})
The issue is that the query does not expect an array,
Please fix it:
type Query {
instant_message(fromID: String, toID: String, msgText: String): [instant_message]
}
Then you should make sure the resolver returns Array of objects, if it doesnt work then the resolver is not returning an Array.

How to change a schema key?

I have a schema defined below and how can I change the predefined schema key (summary: key) via meteor template?
Schemas.Books = new SimpleSchema(
{
summary: {
type: String
}
}
);
For instance, I want to change this key through a session variable that was defined by router or through a user input.
Not Sure, Try this
If your schema is like this
Books = new SimpleSchema(
{
summary: {
type: String
}
}
);
then in tempalte helpers,
Books._schema.summary.type = function() {
return Session.get("typeValue");
};
In my project I have schema like this
RegisterSchema = new SimpleSchema({
name: {
type: String
},
email: {
type: String,
regEx: SimpleSchema.RegEx.Email
},
password: {
type: String,
label: "Password",
min: 8
},
confirmPassword: {
type: String,
label: "Confirm Password",
min: 8,
custom: function () {
if (this.value !== this.field('password').value) {
return "passwordMismatch";
}
}
}
});
and I'm dynamically setting optional value for email like
RegisterSchema._schema.email.optional = function() { return true };
this worked for me.
All d best
This is not the thing that I'm trying to do but I have learned a new trick : )
I want to change the schema key that I described above like this.
Books = new SimpleSchema(
{
bookName: {
type: String
}
}
);
Changing summary: with bookName:
Actually I want to define schema keys dynamically with respect to user information (userId, userName etc.).

How to use encryption in ydn-db database library?

I am trying to implement setSecret to encrypt the values in indexeddb but get the error:
"unable to call method setSecret of undefined"
Code Below:
$(window).load(function () {
//Database Schema
var db_schema = {
stores: [
{
name: "Employees",
}
]
}
var secret = "Test";
db.setSecret(secret);
db = new ydn.db.Storage('Database', db_schema);
});
Following the link, but not sure where I'm going wrong any ideas:
Anyone encrpyted there indexddb values before?
Thanks
Sorry for documentation behind. I have updated the documentation. Now you have to put encryption key in database options.
var schema = {
version: 1,
stores: [{
name: 'encrypt-store',
encrypted: true
}]
};
var options = {
Encryption: {
expiration: 1000*15, // optional data expiration in ms.
secrets: [{
name: 'aaaa',
key: 'aYHF6vfuGHpfWSeRLrPQxZjS5c6HjCscqDqRtZaspJWSMGaW'
}]
}
};
var db = new ydn.db.Storage('encrypted-db-name', schema, options);
You have to use "-crypt" module to get that feature. It supports transparent data encryption using sha256 crypto, per record salting and key rotation. You still need server to generate encryption key and send to the client securely. There is also a demo app.
//Database Creation
//Database Schema
var db_schema = {
stores: [{
name: "DataTable",
encrypted: true
}
]
};
var options = {
Encryption: {
//expiration: 1000 * 15, // optional data expiration in ms.
secrets: [{
name: 'aaaa',
key: 'aYHF6vfuGHpfWS*eRLrPQxZjSó~É5c6HjCscqDqRtZasp¡JWSMGaW'
}]
}
};
//Create the database with the relevant tables using the schema above
db = new ydn.db.Storage('Database', db_schema,options);
$.ajax({
type: "POST",
url: "/home/DownloadData",
data: { File: file },
success: function (result) {
var Key = result.Data.Key;
var DownloadedData= {
Data: result.Data,
Data1: result.Data1,
Data2: result.Data2,
Data3: result.Data3
};
db.put('DataTable', DownloadedData, Key);
return false;
},
error: function (error) {
alert("fail");
}
});

Resources