Jump to content

FireWire

Members
  • Posts

    266
  • Joined

  • Last visited

  • Days Won

    18

Everything posted by FireWire

  1. That's right, it's a 2 for 1 special. I am using WireHttp to make a GET request but it is actually making 2 requests when calling WireHttp::get() only once. It doesn't matter where I make this call, it always sends 2 requests. I stripped this down and wrote the request code in init.php to test with the bare minimum of ProcessWire booted. Here's my code: <?php namespace ProcessWire; /** * ProcessWire Bootstrap Initialization * ==================================== * This init.php file is called during ProcessWire bootstrap initialization process. * This occurs after all autoload modules have been initialized, but before the current page * has been determined. This is a good place to attach hooks. You may place whatever you'd * like in this file. For example: * * $wire->addHookAfter('Page::render', function($event) { * $event->return = str_replace("</body>", "<p>Hello World</p></body>", $event->return); * }); * */ if (!defined("PROCESSWIRE")) die; $http = new WireHttp; // Create unique URL with random number to track method call vs. requests made. $url = 'https://renovaenergy.ngrok.io/processwire/test/init/' . rand(1, 9999); $http->get($url); die; Here's the requests I'm receiving after loading the page once: That test was done with all modules removed from the modules directory and the module cache cleared. I can't think of what is causing one get() call to create two requests. Running PW v3.0.184
  2. @monollonom Good observations on that. I think the regex section could use an example like the others on that page. I just wasn't able to visualize that. Many many thanks for your assistance an insight on this!
  3. @dotnetic I picked it up after developing our API in Slim and looking at some best practices. It would be really great if this was the ProcessWire default.
  4. Some follow-up thoughts. Even though @monollonom had a more elegant Regex string that works, I still wanted to find out if I could make my ugly string work since technically it should have and there might be a case where an alternate isn't possible. I found some curiosities that may help some other people if they run into a similar problem. Original string: '/api/v1/offline-events/{eventId:#(?=.{15}$)([A-Za-z0-9])\w+#}/?' First off, I had to remove the # regex delimiters at the start/end. Then I had to replace the {eventId:regex} curly braces and apply parenthesis (eventId:regex) then it worked with the ugly regex. New String: '/api/v1/offline-events/(eventId:[[:alnum:]]{15})/?' This was a little confusing because in the URL hooks documentation I just noticed that /route/(variable) and /route/{variable} are used interchangeably. The second issue is that the documentation states the following: Using any of the !@#% characters at the beginning/end of the regex expression caused it to fail whether using {} or () to surround the route argument. So long story boring, I'm not sure if the documentation could be clarified or if there's a bug somewhere (or if I'm just reading it all wrong). Documentation I am referring to here for reference. Something @ryan should review?
  5. @monollonom HECK YEAH! If there's anything that demonstrates my complete lack of regex abilities... it's this post. Excellent 404 fix. First time using the URL hooks and didn't know if there was a "URL Hook way" of handling.
  6. You're 100% right about the DB storage of keys for modules. My use case for the credentials in .env is for non-module related needs that are necessary in various scripts around the codebase. Some of which aren't in the ProcessWire namespace so wire() & $config aren't available. A good example is where I work I've built a company-wide REST API to interact with our systems so those keys are in .env. It makes it very easy to work with at a glance. With clean variable names I haven't run into any $_ENV pollution/collisions. Two custom variables that we do create are $config->envIsProduction and $config->envIsDevelopment to help alter code behavior when needed, we use that to do things like switch scripts in markup (like production/development Google Tag Manager/Analytics). Here's a more robust (dummy) example of our local development .env, ENVIRONMENT="development" # Either production or development # CMS CMS_DEBUG="true" CMS_CHMOD_DIR=0755 CMS_CHMOD_FILE=0644 CMS_USE_PAGE_CLASSES="true" CMS_USE_FUNCTIONS_API="true" CMS_PREPEND_TEMPLATE_FILE="_init.php" CMS_USER_AUTH_SALT="d5e3ac4deba1e382255bbd8755d7e713" CMS_LOCALE="en_US.UTF-8" CMS_TIMEZONE="America/Los_Angeles" CMS_DEFAULT_ADMIN_THEME="AdminThemeUikit" CMS_INSTALLED=1580677417 CMS_MODULE_INSTALL="true" # CMS Database - Development CMS_DB_HOST="127.0.0.1" CMS_DB_NAME="pw_website_db_name" CMS_DB_USER="db_user_name" CMS_DB_PASS="hB99kVrqS444VZlrrr" CMS_DB_PORT="3306" CMS_DB_ENGINE="InnoDB" # Renova Energy API - Development RE_API_URL="https://secure-tunnel-url.ngrok.io/" RE_API_KEY_WEBSITE="d5d891e204f5473990bb533cf7fca22f" RE_API_KEY_EVENT="531706b9837744ecbbf2b008bc11a681" # Mailgun MG_KEY="5af07ec6-315c-48d9-b615-f1cfb3d75820" MG_DOMAIN="mg.ourconfigureddomain.com" # Forecast.io FORECAST_IO_KEY="5fce4a3251f711ecbf630242ac130002" # CallTrackingMetrics Webhook Auth Token CTM_WEBHOOK_AUTH_HASH="227040707a1b4e13bc88facf928defe0" # Web API Authentication Keys WEB_API_KEY_SALESFORCE="84f13985-77f5-4521-9c2d-1567ddb9bf2e" WEB_API_KEY_APP="e7051f6e-5905-47f6-9108-93d2f02a53b8" Also, thank you for the kind words about Fluency, looking forward to the next big (biggest yet) release soon!
  7. I'm a little late to the game on this but wanted to throw out what we use on our PW sites. We keep all credentials in .env files in the root directory and then loaded using a package called phpdotenv. The .env file is loaded and then the credentials can be accessed at runtime via the $_ENV global. Some further details on this setup: .env files are automatically protected system files in Apache and will not be served (unless someone actively overrides this, but that would be bad). These files are not added to the Git repository and never stored. We have .env files for local, staging, and production. The contents of each file are stored in whole as a secure note in our password manager. The dotenv library is loaded once in config.php and the values are available globally. We also store credentials for external APIs and services. This allows us to store not only credentials, but any values that differ between local/staging/production. We store all of our config.php variable values in .env so that the config.php file is environment agnostic and we can always be sure that the .env is the single source of truth for the entire CMS configuration. We use Git to deploy to staging/production servers so using .env files allows us to push all of our code while knowing that sensitive information and data that changes between environments never gets mixed up. Also makes it very clear to anyone looking at the code that these values are stored in a dedicated system dot file. Here's the package, can be installed with composer https://github.com/vlucas/phpdotenv This is what a config.php file looks like with it in use: <?php namespace ProcessWire; // Load env variables from .env in root directory $dotenv = \Dotenv\Dotenv::createImmutable(__DIR__ . '/../'); $dotenv->load(); $config->debug = filter_var($_ENV['CMS_DEBUG'], FILTER_VALIDATE_BOOLEAN); $config->usePageClasses = filter_var($_ENV['CMS_USE_PAGE_CLASSES'], FILTER_VALIDATE_BOOLEAN); $config->useFunctionsAPI = filter_var($_ENV['CMS_USE_FUNCTIONS_API'], FILTER_VALIDATE_BOOLEAN); /** * Database Configuration */ $config->dbHost = $_ENV['CMS_DB_HOST']; $config->dbName = $_ENV['CMS_DB_NAME']; $config->dbUser = $_ENV['CMS_DB_USER']; $config->dbPass = $_ENV['CMS_DB_PASS']; $config->dbPort = $_ENV['CMS_DB_PORT']; $config->dbEngine = $_ENV['CMS_DB_ENGINE']; // Etc... Hope this might be useful to someone!
  8. Hey all, I've been building a new feature on our PW site and the URL hooks are exactly what the doctor ordered. I am developing a RESTful web API to allow external platforms to integrate with our site. The API endpoints are namespaced at /api/v1. I am having trouble making use of the named route parameter using regex. I have a hook for /api/v1/offline-events that gets all Offline Event pages. The next route to be defined is /api/v1/offline-events/{event ID}. The event ID is using a custom string (not the Page ID) that is a 15 character alphanumeric string like this: E4LxQRXZadgjstw. However when I use a PCRE compliant regular expression (tested on regexr.com) I get an error. Here is my hook code for reference and the error produced: <?php namespace ProcessWire; $wire->addHook('/api/v1/offline-events/{eventId:#(?=.{15}$)([A-Za-z0-9])\w+#}/?', function($e) { // ommitted for brevity }); // Error thrown: Warning: preg_match(): Unknown modifier '(' in /wire/core/WireHooks.php on line 1170 I've tried using all delimiters in the documentation (!@#%) but no change in the outcome. The second question is how do I create a wildcard capture for all 404s that occur after the /api endpoint? Currently it is loading the website 404 page. Many thanks!
  9. I am finishing the next release right now and will be pushing a new version. In this version you can customize all Fluency UI strings for any default language, using the translation service if desired.
  10. Okay now I got it. That is the URL that needs to be in the JS file I mentioned. In that JS it does it's best to parse the URL, get the admin slug, then build the request URL. If you revisit that code in fluency_tools.js set the value of requestUrl to where it should be able to send requests to the module. It should look like this: var moduleRequest = function(requestData, callback) { var winLoc = window.location, params = [], requestUrl = 'https://domain.com/_tmp/processwire/fluency/data/' // requestUrl = winLoc.protocol + '//' + // winLoc.host + '/' + // winLoc.pathname.split('/')[1] + '/fluency/data/' // ... ommitted for brevity ... } If you move to production and ProcessWire is being served from the root directory then change this back.
  11. Go to the Fluency module configuration page, then click on the "Translation" link in the menu bar. What is the URL of the page that loads?
  12. Added a fix for the PayPalm img. Thanks for mentioning. Will be included in the next release. I hadn't anticipated an installation in a subfolder. The module creates an admin page when installed and that page's URL is an endpoint for the JavaScript on the page to make AJAX calls to when getting/sending translation data. The JS assumes that this URL will be at the root level. The JavaScript can't tell if the site is in a subdirectory. I don't know how to code the JavaScript to figure that out since it is separate from the CMS and the module which can tell what the full proper URL is but the JS doesn't have a way to get that info. There is probably a way to solve this problem but it will take a little investigating. There is a quick and dirty solution that would fix this issue for you right now. That would be to go into the module directory, navigate to /src/js/ and then edit fluency_tools.js to point to the full URL you need by changing line 32. From this: winLoc.pathname.split('/')[1] + '/fluency/data/' To this: winLoc.pathname.split('/')[1] + '/_temp/fluency/data/' That will let the JS know where to get/send translation data. If/when you need to move your PW site to the root directory then change it back to the original value. Let me know if that works for you.
  13. ProcessWire definitely shines in the security department and the login page does have throttling. I don't know what your threat model is but usually sites have to deal more with bots than individual bad actors, but that depends on the purpose/use for your site. I've built many PW sites over the years and not one has ever been compromised. In my opinion, your biggest threat as far as hackers go would be a person that came into possession of one of the users' login credentials or much more common automated attack scripts with other vectors like requests containing data that the code isn't prepared to handle, or MySQL injections in your forms. Here are some additional thoughts on your login URL. If you don't want bad actors to know the login URL then it should be changed it to one that is practically unguessable like /clientname-admin-login or something easy to remember but hard to guess. Consider that your /processwire login URL is not unknowable because it's the default. Someone intent on getting to the login page or knowing what CMS you are using could analyze the markup and see that your images are being served from /site/assets/files/{page id} and any assets like JS may be served from the templates directory like /site/assets/templates/scripts- the file structure consistent across ProcessWire sites. When you load a page on a ProcessWire site, the server returns the request with the header "x-powered-by: ProcessWire CMS" unless you've disabled it and that will let someone look up what the default URL would be. Using /processwire in JS isn't really the issue. All that aside, it's not automatically a disadvantage to have your login URL known. Most of the PW sites that are built probably keep /processwire. My take is that if you have the opportunity to change it and reduce the chance non-authorized people would see the login page to begin with, why not? If this were my project I would change the login URL and create a dedicated /api page in the admin then use a hook to hide it in the page tree on render for non-superusers. It would keep the main site tree tidy as desired, allow for a clean semantic URL to work from, and not hard code in references to a part of the website that isn't content-related. If you want to take security against bots into consideration I would look into adding some bot blocking rules to your .htaccess file, I use 7G Firewall. Bot blocking prevents bot HTTP requests from requiring ProcessWire to boot up, analyze the URL, determine that it doesn't exist, and then serve the 404 page- this improves performance by reducing server load. Blocking bots also takes care of many other automated malicious requests as described above. I kinda blew this open a bit, but I think your question about security being limited to hackers and the login page could benefit from a wider scope.
  14. I had initially written off mass translation because after seeing the time it took to translate one or two fields I thought it could be a big holdup for the user. Have you run into any situations where a whole page runs into problems? This is really awesome work!
  15. @Robin S Appreciate the help! I was also thinking about a possible conflict between the selector and the value. Will work with your ideas. Cheers!
  16. Hey all. I have a search feature built into our website but it won't match a whole word containing a character, in my situation the % character. When I look for "50%" it brings up results with 50 in it, but does not match pages with 50%. I've tried with several selectors including *=, **=, ~=, and attempted an advanced search with #=+50%, but no dice. I've also tried with and without sanitizers including $sanitizer->selectorValue(); Any insights? Thanks!
  17. I'm all about devdocs.io We need to boost those Github stars...
  18. It would be pretty complex to create settings for that in the module config on a per-field basis and I think it might be too much of an edge case to implement in the module directly so I think hooking would be your best bet on this. Using `addHookAfter();` is the way to go. Just remember to test the output of `___executeData()` as it returns different types of data depending on the request, see each case in the switch statement in the `___executeData()` method. Here's some quick info that might help you get up to speed more quickly. All of the return values from `___executeData()` have the same data structure for predictability when used. At the very least each return value has `data` and `httpStatus` properties/values. A good way to make sure you are dealing with a translation is to decode the JSON (we'll say it's assigned to $decodedResponse), and then look for `$decodedResponse->data->translations;`. If the `translations` property exists in `data` then you know it's a translation. You would want to append your string to `$decodedResponse->data->translations[0]->text;`, encode `$decodedResponse` again, then return the modified JSON.. I'm not sure how you would be able to detect what field has been translated though because the return data from `___executeData()` doesn't contain any field name so your hook would append to all multi-language fields. Let me know if you can't find a workaround for this and I'll see if I can help. Dunno if that is what you were looking for but hope it helps!
  19. New version released. Fixed issue when translating larger volumes of text. In testing I was successful in translating over 20,000+ words in one field. When you get to large volumes of content like that there is a very noticeable amount of time it takes to complete that request, but it does it. Download the newest alpha here: Fluency 0.3.2 This should solve your issues @B3ta, let me know if you experience any issues.
  20. @B3ta That was all totally wrong. I was improperly making the DeepL API call with the wrong method which was totally my fault. After working on the issue I've tested translations with a lot of content and have had success up to ~22,000 words (rich text in a CKEditor field). If your PW fields has more than that, I'm impressed haha. That will have to be the new ceiling and I'll engineer a solution if people start hitting that. When working with content up to those levels though I think DeepL may be being generous with their stated API request size limit so keep in mind that number could fluctuate- just hypothesizing though. You should be more than okay when translating 5000 words though. Will push a new version soon and let you know when it is ready.
  21. @B3ta Update on the errors with lengthy content. Unfortunately it's not an issue with the module from what I can see. I was able to find out where the limitation on length was down to the sentence. When the API is used to translate it returns standardized responses that returns the translated content when it is successful, or errors that give instructions on what went wrong. Unfortunately the issue we are experiencing causes the DeepL API to return nothing (null) which means that their system experiences and issue but does not respond the way that they say it should. I'm going to be sending in a support request to DeepL detailing the issue and see what they say. Will report back with updates but as of right now it looks like Fluency can only handle medium amounts of text.
  22. I thought about building that out from the start but wanted to focus on getting the core of the module working first in a way that matched the way ProcessWire's multi-language setup works where there is a primary language and secondary languages. Including the general translation tool in the top menubar where any text can be translated from/to any language was a short term solution for that limitation. Once Fluency is able to mature and all of the bugs fleshed out then revisiting that would be an option.
  23. I've seen translations take varying times depending on length and language. Are you letting it work for a while? I will test more with longer content and look into how DeepL handles it.
  24. @B3ta New version pushed with fixes for the [[tag]] exclusion. All excluded strings set up in the module config should work now. https://github.com/SkyLundy/Fluency-Translation/releases/tag/v0.3.1 Still need to work on the large content translation though.
×
×
  • Create New...