Jump to content

will

Members
  • Posts

    37
  • Joined

  • Last visited

Everything posted by will

  1. How does one place an order just by interacting with the API rather than the order form? I'd like to replicate all the actions that would occur when using the order form. New users can be created with the User model, but what needs to be done to ensure that a new service is created and invoiced? A new service could be created via Services->Add. This can even notify the user that the service has been created. Will it create the initial invoice as well, and activate the service once that invoice has been paid, or does the order plugin need to be used for all of that to happen? The order plugin has models available that aren't documented at http://source-docs.blesta.com/package-blesta.app.models.html (presumably because they are plugin models rather than base Blesta models) It looks like the "add" function in plugins/order/models/order_orders.php may be what I'm looking for - is that all I need to call, or is there some additional work that needs to be done to complete this process?
  2. I'd like to add a tab to the logs page under the Tools section for a plugin I'm building. Is this possible? What's the best way to go about this? Are there any plugins that implement this that I could look at? I noticed the PHPIDS plugin implements a logging system, but it keeps its logs under its own management page rather than adding them to Tools>Logs.
  3. Is Blesta backwards compatible with modules from 3.6.2? Does anything need to be changed for a 3.6.2 module to work with Blesta 4?
  4. Is there a changelog for the updates made between Universal Module 1.3.1 and 1.4, the version offered in the Blesta 4.0.0. beta 1?
  5. It looks like CORE-710 is marked as private - I get a login screen when I try to take a look at it. ( http://dev.blesta.com/browse/CORE-710 ) Can it be changed to public?
  6. If this is not a current feature of Blesta, then yes please.
  7. Is it possible to include all outstanding invoices whenever Blesta emails a customer about an open invoice? We've had a few cases where a transaction was not recognized by Blesta, so a customer thought they paid the invoice but Blesta did not, and that invoice languished while the customer kept up to date with subsequent invoices. Alternatively, a line indicating the total amount due for an account (rather than, or in addition to, the amount due for the invoice) would probably suffice to get a customer to log in to the billing panel where they would notice all outstanding invoices.
  8. Don't forget to configure your SSL for stronger security! See https://mozilla.github.io/server-side-tls/ssl-config-generator/ to help you decide on what level of security you want to employ. The trade-off that comes with the strongest of security is dropping support for older browsers. For most of Blesta's markets, I suspect you won't be breaking things for very many customers if you go with "modern" security, and chances of breaking things for *any* customers are slim if you go with "intermediate" security. "Old" security includes support for SSLv3 which is known to be broken. Do not use the "old" option unless you absolutely have to. (Warning: if you haven't configued OCSP stapling or HSTS before, I strongly recommend you test them on a non-production server first, as screwing the config up make your site inaccessible... potentially for the duration of max-age. Use a very small max-age while testing.) The config generator mentions a "dhparam.pem." You can generate a DH parameter file with openssl dhparam -out dhparam.pem 2048 You want at least 2048 bits in light of the Logjam attack. We force SSL for all connections to Blesta. (Also, if you want to support ipv6, you'll need to specify that you want to listen on ipv6 interfaces.) server { listen 80; listen [::]:80 ipv6only=on; # This last flag can fix some issues nginx can have with binding to ports. server_name mydomain.com; return 301 https://$server_name$request_uri; #Force SSL } server { listen 443; #SSL Only listen [::]:443 ipv6only=on; #For ipv6 server_name mydomain.com; # The rest of the config goes down here } EDIT: If you want to be paranoid (e.g. security bonus points) your config directory should be readable by PHP, but not nginx. Similarly, your SSL certs should be readable by nginx, but not PHP. On top of that, your DB should be protected by your firewall - there's no reason for it to be listening to any requests except local ones. One more thing: you can tell nginx to ignore requests for sensitive files or folders. location ~ ^/(cache|config|errors|helpers|internal|language|lib|index.php/api|api) { deny all; return 404; } # If you're using your API with some kind of external service, you can remove those last two. # If that service has a static IP, you can add "allow x.x.x.x;" on the previous line, where x.x.x.x is the service's IP.
  9. +1 It would be great to have access to a git repository for the purpose of pulling in updates, and being able to send pull requests upstream would also be pretty nifty. As a suggestion to the OP, the way we do it is we maintain two branches - master, which tracks the official codebase, and a branch with our production changes. When there's an update, we drop the update on to the master branch and then merge that in to our production branch. If these are Git repositories, Git actually makes this fairly easy with the submodule feature. (Even if you don't publish a repo, this feature may be useful to you internally.) PS I don't have any experience with JIRA outside of tracking issues as a Blesta customer, so there may be benefits I'm not aware of, but if the only real stumbling block for using JIRA rather than GitHub issues as you migrate to Git from SVN is the concern of loss of tickets & corresponding history, this tool might be worth looking at to ease migration. https://github.com/brianhayes/jira-to-github-issues
  10. Yeah, it looks like Swiftmailer supports S/MIME, but I think that's of less interest to our customers. It does look like I can add parts to the body through Swiftmailer, though, so I'll probably modify the send function in /components/email/email.php to change the message's type to "multipart/signed", compute a signature for the "text/plain" portion, and add a part named "application/pgp-signature" with that signature contained. If anyone's interested in the code, I can share it when I'm done. (It's pretty low on my priority list right now, though, and it will unfortunately be hardcoded, not exposed through the admin console.)
  11. Several of our customers have inquired whether or not we could sign our communications from Blesta with GPG. (Doing so with PGP would probably be even better.) How hard would this be to implement? What part of the codebase would need to be modified?
  12. That's weird. Those pages do seem at odds with their API page; it looks like it's supported by their API. From https://bitpay.com/api /invoices/:invoiceId/refunds Creates a refund request for the given invoice. Response Name Type idRefund request resource idstring requestDateTime of API calldate statusCan be `pending`, `success`, or `failure`string tokenAPI token for invoice refund request resource EDIT: It looks like it's a relatively recent addition to their API. http://blog.bitpay.com/2014/09/18/announcing-the-new-bitpay-api.html
  13. Are there any plans to add support for refunds to the Bitpay gateway?
  14. I imagine their motivation is the increased speed, security, and privacy that comes with disabling JS. I'm not interested in debating whether or not this is a reasonable choice to make; I don't think our company has any business criticizing the browsing habits and security procedures of our users. If they don't want to use JS, as far as I'm concerned that's their prerogative. Ok. We've had fewer than a dozen complaints, so we're planning on simply offering to handle any interactions they need to take care of through our support email system rather than through the website.
  15. We put Blesta in to production recently and a few of our customers have complained that the site doesn't work for them without JS enabled. Is it possible to get it working without JS, or is that integral to functionality? I'm talking strictly about client-facing areas; having JS on the admin side is not something we're trying to work around.
  16. Um, as far as I could tell during my testing, adding an existing pending service (e.g. "Activate service") used Services:add, not Services::edit. Thanks for the tip about injection; I was just about to test that. Is this the correct translation using Record's methods? public function validateAbsent($hostname, $service){ Loader::loadComponents($this, array("Record")); // Query DB to see if this hostname exists already $this->Record->select('1')->from('service_fields')->innerJoin('services', 'service_fields.service_id', '=', 'services.id')->where('service_fields.key','=','hostname')->where('service_fields.value','=',$hostname)->where('services.status','in',"('active','suspended','pending')"); if ( !is_null($service)) { $this->Record->where('services.id','!=',$service->id); } return($this->Record->numResults() < 1); } (or, for readability's sake) public function validateAbsent($hostname, $service){ Loader::loadComponents($this, array("Record")); // Query DB to see if this hostname exists already $this->Record->select('1') ->from('service_fields') ->innerJoin('services', 'service_fields.service_id', '=', 'services.id') ->where('service_fields.key','=','hostname') ->where('service_fields.value','=',$hostname) ->where('services.status','in',"('active','suspended','pending')"); if ( !is_null($service)) { $this->Record->where('services.id','!=',$service->id); } return($this->Record->numResults() < 1); } Edit: I couldn't get the "in" operator working. I also had to unbind my inner join statement. This seems to be working: public function validateAbsent($hostname, $service){ Loader::loadComponents($this, array("Record")); // Query DB to see if this hostname exists already $this->Record->select('*')->from('service_fields')->innerJoin('services', 'service_fields.service_id', '=', 'services.id', False)->where('service_fields.key','=','hostname')->where('service_fields.value','=',$hostname)->open()->where('services.status','=','active')->orWhere('services.status','=','suspended')->orWhere('services.status','=','pending')->orWhere('services.status','=','in_review')->close(); if ( !is_null($service)) { $sid = $service->id; $this->Record->where('services.id','!=',$sid); } return($this->Record->numResults() < 1);}
  17. It appears that UniversalModule::addService is the one invoking processService in my case, and it looks like $service is not passed to UniversalModule::addService from Services::edit (/var/www/app/models/services.php line 1028) though it *is* passed to UniversalModule::editService. It looks like adding that to the argument list will probably fix my problem. Is there a reason that $service is passed to editService but not addService? Could that be changed upstream? In my case, I modified app/models/services.php to pass it in for me, but I expect that may conflict with future updates. If anyone wants to duplicate my validation for uniqueness function, here it is. It expects to be passed the hostname label and $service. public function validateAbsent($hostname, $service){ Loader::loadComponents($this, array("Record")); // Query DB to see if this hostname exists already if (is_null($service)){ $rows = $this->Record->query("select 1 from service_fields inner join services on service_fields.service_id=services.id where service_fields.key = 'hostname' and service_fields.value = '$hostname' and services.status in ('active','suspended','pending')")->rowCount(); } else { $sid = $service->id; $rows = $this->Record->query("select 1 from service_fields inner join services on service_fields.service_id=services.id where service_fields.key = 'hostname' and service_fields.value = '$hostname' and services.status in ('active','suspended','pending') and services.id != $sid")->rowCount(); } return($rows < 1); } EDIT: Fixed to accommodate $service being null, which it will be at some point during the ordering process.
  18. I'm trying to add validation to Universal Module to ensure that no service with the same service field "hostname" is already provisioned. (That is, the hostname should be unique.) Universal Module doesn't yet offer a way to ensure a field is unique. These services are manually activated. To validate, I'm writing a custom validation function that interrogates the tables "service_fields" and "services." Conditions I need to ensure: 1) There is not a service_fields row with our hostname that corresponds with a services row with a status of "active" or "suspended" 2) There is not a service_fields row with our hostname that corresponds with a services row with a status of "pending" or "active" or "suspended" and a non-matching client_id. Ideally, I'd also like to ensure that 3) There is not a service_fields row with our hostname that corresponds with a services row with a status of "pending" and with a non-matching service_id. What do I need to change to have the services.id integer available in the function validateService? It's ok if it is NULL because no row yet exists for the service being validated, such as at order time instead of activation time. Alternatively, is it possible to call different validation functions at order time and at activation time?
  19. We ran in to this problem and were confused for a couple days when we removed the password from the template but it kept showing up in the logs, despite it not appearing in the test emails we sent. It turns out there are two templates - one HTML, one text, and only the text template is saved in the logs. Perhaps something could be done to make this more obvious?
  20. Now that user-initiated upgrade/downgrade is available, is it possible to require approval for those as well? If there's no provisioning module attached to the order form, allowing an upgrade/downgrade is just going to let the user choose a new price for the same service.
  21. Does Blesta sanitize/escape values it reads from the database? It seems to sanitize user-input written to the database, but I'm wondering how careful I need to be if I'm writing directly to the database. (e.g. bypassing blesta)
  22. http://docs.blesta.com/display/dev/Error+Checking has some erroneous information in it. Under the heading "Custom Rules" the documentation instructs the developer to create a function "getRules()" getRules() may have been called to retrieve the rules for a custom field in previous versions, but it is no longer called. (I have not tested this in the present beta release.) Either getRules() needs to be called once again to retrieve those custom rules, or documentation should specify that the function validateService is the function that needs modification. This is the way I modified validateService to include my rules. I added these lines immediately before the line $this->Input->setRules($rules); The first parameter of rules, "hostname", identifies the variable the rule is for. The second parameter, e.g. "format" is an arbitrary name you are assigning to the rule. It must be unique within the scope of the variable. (That is, two variables can have a rule with the same name, but a single variable must have different names for all of its rules.) $rules["hostname"]["format"] = array( 'pre_format' => array(array($this, "wrap_strtolower")), /* wrap_strtolower is a function in the same class as this function. It simply returns strtolower($inputstring) because strtolower() is not accessible as a callback function. The function returns a string which will be passed to the rule. */ 'rule' => array("matches", "/^[a-z][a-z0-9]{2,31}$/"), 'message' => 'Hostname is incorrectly formatted. It must be between 3 and 32 characters. It must begin with a letter and contain only letters, numbers, and dashes.',); $rules["hostname"]["absent"] = array( 'pre_format' => array(array($this, "wrap_strtolower")), 'rule' => array(array($this, "validateAbsent"),), /* validateAbsent is a function in the same class as this function. It returns true if it finds that its input is valid, and false if not. */ 'message' => "This hostname already exists."); Directly setting $rules to an array as recommended by the documentation should be considered harmful because it will clobber any rules already set, such as checking that the field is required (if that was specified in the module configuration). I've made this bug report verbose to assist anyone who was confused by the documentation.
  23. Aha! That's exactly what it was. Thank you kindly.
  24. Yes, as I said, it's not getting logged. Nothing to /var/log/nginx/access.log, /var/log/nginx/error.log, nor /var/log/nginx/php_errors.log, all of which I've confirmed normally receive logging output. For example, if I visit a php page consisting of <?php throw new Exception('Noooooo!'); ?> I get 2014/08/26 11:48:17 [error] 19912#0: *83 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught exception 'Exception' with message 'Nooooo!' in /var/www/error.php:1 Stack trace: #0 {main} thrown in /var/www/error.php on line 1" while reading response header from upstream, client: x.x.x.x, server: mydomain.com, request: "GET /error.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "mydomain.com" After doing further research, it looks like Fatal errors bypass normal error handling. I thought perhaps this was the case here, so I made another error file. <?php throw_error("Nooo!", E_USER_ERROR); ?> but no luck; I still got a logged error. 2014/08/26 11:52:22 [error] 19912#0: *90 FastCGI sent in stderr: "PHP message: PHP Fatal error: Nooo! in /var/www/error.php on line 1" while reading response header from upstream, client: x.x.x.x, server: mydomain.com, request: "GET /error.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "mydomain.com" I turned display_errors on. For my fatal error, I get Fatal error: Nooo! in /var/www/error.php on line 1 However, for https://mydomain.com/index.php/admin/settings/company/modules/available/ I still get a blank page and nothing in the error log. I assume this means I have the wrong sort of Fatal error due to third-party documentation like http://blog.elijaa.org/index.php?post/2010/04/20/Handling-fatal-error-in-PHP-with-register_shutdown_function which describes the blank page I'm stuck with. Right now I'm trying to hunt down other ways to replicate this error.
×
×
  • Create New...