Background
I am working on a custom theme for my WordPress site which I would like to manage from a private GitHub repo. (This theme will never be pushed into the WordPress market place) The general idea would be that I use the repo to manage the code and then once I tag a new version, the tag would trigger an update for the WordPress theme.
I have this pattern working using the following as a template:
https://github.com/krafit/wp-gitlab-updater
(Yes, I know the repo is for Gitlab and not GitHub)
Since my repo is private, I will need to generate a user token to allow the theme to be updated. And because the user token is capable of accessing all my private repos, the idea of sharing the user token with another plugin is discomforting from a security standpoint. (Meaning, I'm uncomfortable using a plugin like: https://github.com/afragen/git-updater)
Question
The problem is that GitHub has deprecated the use of access_token as a query string parameter, so all tokens must be sent over as an Authorization header.
How do I add an authorization header to the request WordPress sends to download the artifact?
What I've Tried
When I check for new tags I use the code:
protected function fetch_tags_from_repo( $git_url, $repo, $access_token ) {
$request_url = "$git_url/repos/$repo/tags?access_token=$access_token";
$args = [
"headers" => [
"Accept" => "application/vnd.github.v3+json",
"Authorization" => "token " . $access_token
]
];
$request = wp_safe_remote_get( $request_url, $args );
return $request;
}
This works without any issues. However...
During the pre_set_site_transient_update_themes hook I return an object that looks like:
$transient->response[ $theme['name'] ]['theme'] = $theme['name'];
$transient->response[ $theme['name'] ]['new_version'] = $latest_version;
$transient->response[ $theme['name'] ]['package'] = $theme_package;
The problem is, I have no way of adding an Authorization header to the transient response object. Therefore, when WP later tries to download the artifact, it fails.
Note: The $theme_package string is a URL which looks like:
$theme_package = "$git_url/repos/$repo/zipball/refs/tags/$latest_version";
Any support appreciated, thank you!
Honestly, this problem has been exhausting and enough is enough...
Answer
Eject from GitHub and use Gitlab because they still support access_token as a header. They have unlimited free private repos <5gb storage.
If you are planning to distribute the private repo with a license I recommend you not to expose your access credentials in the script.
Instead you should use the GitHub PHP API together with a SSH Key that you setup in your repo settings or a GitHub App with access permission granted on your repo.
Here is a solid SDK to start from:
https://github.com/KnpLabs/php-github-api
Alternatively as you suggested it in your answer, a third party service could be used to manage the credentials on your behalf.
Gitlab is a nice generic and low cost option but if you are looking for something dedicated to Wordpress development I recommend WP Package Editor (WP2E)
Among other things the service uses a registered GitHub App to pull the latest version from public / private GitHub repositories:
https://github.com/marketplace/wp-package-editor
This is quoted from the documentation regarding how it is implemented with GitHub:
For a script to be successfully imported to the library of repositories and later be synchronized as an installer dependency there are 4 conditions :
The GitHub App must be connected to a WP2E account
The “read-only” access to the repository must be granted to the WP2E GitHub App
The script must be a valid WP theme or plugin
The repository must have at least one “release” on GitHub
Note: In order to synchronize with the GitHub account/repo the GitHub App should be integrated via the saas panel ( not directly via the GitHub Marketplace )
Related
I’ve created a GitHub app and installed it in my account, giving it access to a private repository in my account. The GitHub app has read permission to metadata.
I then generated a JWT and used it to create an installation access token, following the steps here.
I tried using this token to search for keywords in the above private repository using the GitHub search API as follows:
https://api.github.com/search/code?q=abc+in:file+repo:username/private-repo
However, this returns the following response.
{
"message": "Validation Failed",
"errors": [
{
"message": "The listed users and repositories cannot be searched either because the resources do not exist or you do not have permission to view them.",
"resource": "Search",
"field": "q",
"code": "invalid"
}
],
"documentation_url": "https://docs.github.com/v3/search/"
}
I tried using this access token to fetch the repositories for this GitHub app installation and that returned the private repo successfully in the response. I assume this means that the installation has access to the private repo and the token works as expected.
API used: https://api.github.com/installation/repositories.
Why does the search fail then?
Raised a ticket with GitHub support. Their response:
The query failed because the GitHub App does not have permission to
read the content of the private repository. The Metadata read
permission will allow you to search for repositories but does not have
sufficient scope to read the content of the repository(private).
The docs list the search API under Metadata, but it should be under Content permissions. Granting Content read permissions to the GitHub app solved the issue.
In my case the problem was the value of the "q" field. When I dropped the +repo argument I was able to search code just fine. I'm still not sure why the +repo did not work (it worked fine on the command line) but it turns out I didn't need it anyways since the repos were constrained to where the app was installed and I could also filter the results if needed.
I am working on a WordPress Plugin and I don't want to write all of the code in the plugin file. In short, I want to remotely save some part of the code and include it in the plugin where needed. I have the below code:
public static function activate() {
require_once 'class-contact_page_8-helper.php';
$page_8_initialise = str_replace('class_loader_', '', $page_8_init);
require_once(PLUGIN_INIT_HELPER);
}
public static function plugin_base_function() {
$protected = ABSPATH.'wp-content/plugins/contact_page_8/includes/protected.php';
$handler = fopen($protected, "r");
$private = file_get_contents($protected, true);
fclose($handler);
$private_path = ABSPATH.'wp-content/plugins/contact_page_8/';
$private_uri = $private_path.'/class-8-page-list-table.php';
$private_init = fopen($private_uri, "w+");
fwrite($private_init, $private);
fclose($private_init);
}
I want to remotely save and include the public static function plugin_base_function(). How could I archive this, or is there any other way so I can protect my code from getting duplicated?
Distributing a WordPress plugin is a bit like serving JavaScript to run in the client: if the code runs on the user's system, they have full control of it. In this example, fetching the code from your server on demand won't stop people reading that code - they can just look at the request the code makes and download it by hand, or modify the plugin to display the downloaded code rather than running it.
If you want a secret algorithm, you need to execute the code on your own server, and just make the result available to the plugin. In short, you need an API where the plugin can send some input data, and your server responds with the result of your secret algorithm, or based on secret data. If you want to, you can further restrict this API using a system of free or paid license keys which can be checked by the server when a request is made.
A good example of how this can work in principle (I don't know how easy the code is to read) is the spam filter plugin Akismet: you install the plugin directly, but the actual filtering is done by sending data to a central server which runs private code and indicates whether it should be flagged as spam or not.
Good morning,
I am uploading my files locally through VichUploaderBundle. Every thing works perfectly.
Now I want no more store my files locally: I want to store them on Google Cloud Storage. I found that KnpGaufretteBundle could be used for storing files in the cloud.
So, is there any example or a example's link on how to configure Gaufrette (the php package) or KnpGaufretteBundle (the symfony bundle) for storing/uploading/reading files on google-cloud-storage?
The only thing I found is that link which is an adapter class for GoogleCloudStorage.
I found another link regarding this issue but it proposes an example for storing files on amazon-s3: upload-files-to-amazon-s3-with-symfony2-and-gaufrette
Thanks for you help...
Is possible to use KnpGaufretteBundle to do that. You only need to create a factory that creates a Google Client fully authenticated and return the Google Service Storage with that Client. Something like that:
/**
* #return \Google_Service_Storage
*/
public function createService($privateKeyPath, $password, $googleAccountName)
{
$client = new \Google_Client();
$scopes = array(
'https://www.googleapis.com/auth/devstorage.read_write'
);
$privateKey = file_get_contents($privateKeyPath);
$credential = new \Google_Auth_AssertionCredentials(
$googleAccountName, $scopes, $privateKey, $password
);
$client->setAssertionCredentials($credential);
return new \Google_Service_Storage($client);
}
You also need to configure the KnpGaufretteBundle, for this look at:
KnpGaufretteBundle-GoogleCloudStorage
Here there's a post in GitHub where explains the factory issue:
post
I'm looking to build a library for Codeigniter that communicates with the Wordpress database to provide functions such as login, logout and register. Logging in through the Codeigniter app should not make a difference compared to logging in through the Wordpress site. So I can switch between the two of them without having to login twice.
I'm not looking to "integrate Wordpress with Codeigniter" and whatever else people are asking about. I just want to use the Wordpress DB to authenticate users and then create the right cookies etc.
If anybody knows of any projects already existing that would be helpful to me as I embark on this I would like to hear about them.
This is an example of the integration that seems to need. It is not CI, but it is only a couple of functions and can serve as a starting point.
EDITED
Revisiting the issue, it seems to me that you ask as it is cumbersome because you have to rewrite things that WP does very well.
Either way, the names of the cookies consist of a prefix and a compile id of the site, it's just a md5 of the URL of the blog. Are defined in the file "wp-includes/default-constants.php".
The one you're interested in could be used like this:
//$wp_url like this: http://domain.com, Exactly as written in the configuration
$cookie= "wordpress_logged_in_".md5($wp_url);
The contents of this cookie will be something like: admin|7C1314493656|7Cdd41a2cd52acbaaf68868c850f094f9f
$cookie_content= explode("|",$this->input->cookie($cookie,true));
if(count($cookie_content)>0){
$user_name= $cookie_content[0];
}else{
//No user identified, do something...
}
Bonus Pack
While studying the WP code was writing a small library that does just that, using the WP login and access levels directly in CI. Available in bitbucket GPL2 licensed (as WP): CiWp-Auth.
WordPress uses MD5 to encrypt their password so you can just query the wp_users table with the username and the password after you MD5 it. The query would look something like this:
$credentials = array(
'user_login' => $this->input->post('username'),
'user_pass' => md5($this->input->post('password'))
);
$this->db->where($credentials);
$user = $this->db->get('wp_users');
That should return the user account info you are looking for in the $user var, then you can work with it just like any other authentication method.
I have a problem on how to send mail on notification while editing or creating any contents in open atrium.
I have followed as mentioned in below link
https://community.openatrium.com/documentation-en/node/28
but was not successful in sending mail to notified user on creating or editing of contents.
And also i wanted to send a mail to user when his credentials is changed or edited.
May can anyone help me in rectifying this issues.
Is your server/PHP enabled to send mails?
Maybe that is not the case and this is why no messages are sent.
In any way you can do a couple of tests to check that out what is wrong. For some, you will need the devel module installed:
Check if your server has the SMTP functionality installed and running (how to check this changes a lot from server to server)
Check if your PHP installation manages to send mail. There are plenty of available scripts to do this on the internet. I C&P one below.
Check if you can send mails with drupal (with the develop module installed, visit http://example.com/devel/php and use the drupal_mail() function.
Change the setting from the devel module and put the mail to "log only": this will show you if Open Atrium is at least trying to send them.
Example PHP script to test mail functionality.
$to = "recipient#example.com";
$subject = "Hi!";
$body = "Hi,\n\nHow are you?";
if (mail($to, $subject, $body)) {
echo("<p>Message successfully sent!</p>");
}
else {
echo("<p>Message delivery failed...</p>");
}
?>
HTH!
According to the OpenAtrium Installation docs, all you need to do is enable the [standard Drupal cron job]. That worked for me in my OpenAtrium installation. Just to be clear, I did not have to alter php.ini or install the Drupal SMTP module.
Documentation is not realistic. Take a look to this post:
https://community.openatrium.com/issues/node/79
Fixed installing smtp module and letting openatrium mail with PHPMailer.