I have been trying to use the google api client in cakekphp 3, but not successful on adding the service account json file to my project.
The below line is mentioned in:
https://github.com/googleapis/google-api-php-client
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
But that doesn't work on cakephp 3. I know I can add it to the .env.default file, but it is not recommended for production.
How to use it then?
This function defines a default credentials setting path to be used, but note that you have not called it yet.
You must "tell" your application to use its default credentials settings.
// app.php
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
// In the file you want to use Google Client
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
CakePHP also can read an specific file for env variables:
// config/.env
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
// Uncomment this part of your bootstrap.php
if (!env('APP_NAME') && file_exists(CONFIG . '.env')) {
$dotenv = new \josegonzalez\Dotenv\Loader([CONFIG . '.env']);
$dotenv->parse()
->putenv()
->toEnv()
->toServer();
}
Keeping your setup on .env files make it easier maintaining all your settings up to date.
Related
Gday,
Quite new to TS and only got a little bit of experience with backend in general, so apologies if I am completely missing the idea.
So I really like the idea of using Google Secret Manager instead of custom env config for Firebase Functions.
Below is all done within a config.ts within my functions dir.
I need to initialize stripe. Traditional tutorials say to do something like the below example:
import Stripe from 'stripe';
export const stripeSecret = functions.config().stripe.secret;
const stripe = new Stripe(stripeSecret, {apiVersion: '2020-08-27'});
I think it would be ideal to change it to this:
import Stripe from 'stripe'
import {SecretManagerServiceClient} from '#google-cloud/secret-manager';
export async function getSecret(name:string){
const [version] = await secrets.accessSecretVersion({
name: `projects/example/secrets/${name}/versions/latest`,
});
return version.payload?.data?.toString();
}
export const stripeSecret = await getSecret("Stripe-API")
const stripe = new Stripe(stripeSecret, {apiVersion: '2020-08-27'});
But this causes an issue with it being async/await on the top level.
What are my options here and what is best practice?
The Google Secret manager is a useful utility and below are a few best practices when using Secret Manager.
You may try and use following to create and use a secret:
From the root of your local project directory, run the following command:
firebase functions:secrets:set SECRET_NAME
Enter a value for SECRET_NAME.
The CLI echoes a success message and warns that you must deploy functions
for the change to take effect.
Before deploying, make sure your functions code allows the function to access the secret using the runWith parameter:
exports.processPayment = functions
// Make the secret available to this function
.runWith({ secrets: ["SECRET_NAME"] })
.onCall((data, context) => {
const myBillingService = initializeBillingService(
// reference the secret value
process.env.SECRET_NAME);
// Process the payment});
Deploy Cloud Functions:
firebase deploy --only functions
You can also access it like any other environment variable. Conversely, if another function that does not specify the secret in runWith tries to access the secret, it receives an undefined value:
To see the complete best practices list, please visit the next link [1] and to know more about managing secret versions, please take a look at the next link [2].
[1] https://cloud.google.com/secret-manager/docs/best-practices
[2] https://cloud.google.com/secret-manager/docs/managing-secret-versions
I'm doing all the work based on the code. I want to work on a simple task of edit and save hostingstart.html in kudu ui, but I don't know how to do it.
Currently, we have checked the connection through Azure app service distribution and dns authentication with terraform, and even checked whether the change is good through hostingstart.html in kuduui.
If possible, I wanted to work with the terraform code, so I wrote it as below and put the html file inside, but it didn't work.
(If it's not terraform, yaml or sh direction is also good.)
resource "azurerm_app_service" "service" {
provider = azurerm.generic
name = "${local.service_name}-service"
app_service_plan_id = azurerm_app_service_plan.service_plan.id
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
https_only = true
source_control {
repo_url = "https://git.a.git"
branch = "master"
}
}
Or can we specify the default path in the internal folder in this way?
tree : web
+page
- hostingstart.html
+terraform
- main.tf
- app_service.tf
site_config {
always_on = true
default_documents = "../page/hostingstart.html"
}
For the moment. It seems best to deploy and apply through blob storage.
(https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_blob)
for Terraform you can’t easily edit that file from management plane APIs, which Terraform would use. Instead, you can deploy a minimal application with whatever you want to show. Here’s an example of deploying code with an ARM template: https://github.com/JasonFreeberg/zip-deploy-arm-template.
I'm trying to help a friend about his nodejs application.
He use NodeMailer to send emails automatically. We both use ubuntu.
To avoid any leaks, the credential for NodeMailer are set as an environnement variable called EMAIL_CREDENTIALS.
In the app, EMAIL_CREDENTIAL is called as follow:
var emailCredentials = process.env.EMAIL_CREDENTIALS;
if (emailCredentials === 'undefined') {
throw Error('Email credentials are not present');
}
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport(emailCredentials);
To set email credential I added a line in src/environnement :
EMAIL_CREDENTIALS={host:"smtp.gmail.com", port: 587, secure: false, auth: {user: "**user**", pass: "**pass**"}}
When I run some test, NodeMailer return the following error
Error: Unsupported configuration, downgrade Nodemailer to v0.7.1 to use it
at Nodemailer.sendMail (/home/**path**/node_modules/nodemailer/lib/nodemailer.js:274:18)
This error happen because type of param === 'string' in nodemailer.createTransport(param) .
My friend has been using this code for a pretty long time with no problem.
Somehow, I understand where the error come from but I would like to know how is it possible that the environnement variable of my friends setup isn't a string and mine is ? And how should I set my variable to be able to run his code without modifying it ?
EDIT: To use JSON.parse() would be a solution but I would prefer not to modifie the app code and as I said this configuration seems to work for my friend so I would like to understand where's the difference.
It is better not to use environment variables for other than simple values. I would suggest you to use a plain JS or JSON file with those variables, that you can simple require(). You can ignore this file via .gitignore, if you do not want it to be included in a git repository.
You can take a look at my configuration module here: https://www.npmjs.com/package/mikro-config
It is designed to be used this way.
Using it, your general configuration will be stored in /config/default.js file, and your environment specific configuration will be stored in /config/env/$NODE_ENV.js file (or in /config/env/$NODE_ENV.local.js, which should be ignored by git, as I described above).
i've build my first Node app in which i need to use 5-10 global variables a lot. The thing is i would like to be able to change those values without restarting the server.
So what i though was setup an interval and update those files either from a ( JSON ? ) file or through a couple of queries to the database.
Now what would be my better option here ? Both mysql and read file modules are used in the app.
Security based wouldn't it be best to place the json file behind the public folder and read from that ? Although without sql injection being possible i think in the DB should be pretty safe too.
What do you guys think ?? Still a newbie in Node JS.
Thanks
With yamljs, the overhead is that you will need to install it. From your question, it seems you are already using a bunch of 3rd party modules in your app.
Why not use something that is a part of node.js itself?
Use the fs module.
Example:
var fs = require('fs');
var obj;
fs.readFile('myData.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data);
});
Docs: https://nodejs.org/api/fs.html#fs_fs_readfile_file_options_callback
A common technique for passing configuration variables to a server is via a YAML file. Normally this file is read once when the server starts but you could periodically query they file to see when it was last updated and if the file was changed update the configuration variables currently in use.
yamljs
YAML = require('yamljs');
config = YAML.load('myfile.yml');
then you can periodically check the last time a file was modified using the mtime property of fs.stat
fs.stat(path, [callback])
If you find that the last modified time has changed then you can re-read the YAML file and update your config with the new values. ( you will probably want to do a sanity check to make sure the file wasn't corrupted etc. )
If you don't want to write the file watching logic yourself I recommend checking out chokidar
// Initialize watcher.
var watcher = chokidar.watch('myfile.yml', {
ignored: /[\/\\]\./,
persistent: true
});
// Add event listeners.
watcher.on('change', function(path) {
// Update config
})
After turning on Google Drive API access from the management console and getting my Client ID keys, I followed the sample code (using Python 2.7) and I am able to insert a folder, set the appropriate permissions (type=anyone,role=reader), and insert a text/html type file into the new folder.
However the JSON file resource objects I receive from executing insert on the drive service have no 'webViewLink' field! There are 'webContentLink' and 'selfLink' fields but 'webViewLink', which is necessary for static HTML publishing, seems to be missing.
Most perplexing. If this feature hasn't been turned on yet or if I need to configure my account settings to allow HTML publishing please let me know. Any other help would be most appreciated ;)
The webViewLink property is only returned for public folders, and not the single files inside such folders. You can use that as the base url to construct links to your files.
The WebViewLink file property can be retrieved by doing something like this:
$file = $service->files->get($file_id, array('fields' => 'webViewLink'));
$web_link_view = $file->getWebViewLink();
OR
$sheetsList = $drive_service->files->listFiles([
'fields' => 'files(id, name, webViewLink, webContentLink)',
]);
$web_link_view = $sheetsList->current()->getWebViewLink();
Pay attention that you should load the file specifying which fields you wanna bring with it (In this case, webViewLink). If you don't do that, only id and name will be available.
If you also need to configure file permissions, you can do something like:
$permissions = new \Google_Service_Drive_Permission();
$permissions->setRole('writer');
$permissions->setType('anyone');
$drive_service->permissions->create($file_id, $permissions);
Possible values for setRole() and setType() can be found here: https://developers.google.com/drive/api/v3/reference/permissions/create