Jump to content

gizmola

Administrators
  • Posts

    5,954
  • Joined

  • Last visited

  • Days Won

    145

Everything posted by gizmola

  1. Maybe this doesn't matter to you either, but ftp has absolutely no transit/network level security. There is a longstanding php library (phpseclib) that implements ssh/sftp https://github.com/phpseclib/phpseclib. There are also php extensions that do the same.
  2. As for your 2nd post, there is a lot of material that you are close to, and I am not, which makes it hard for me to really see the forest through the trees. I don't see Roles/ACL being different things. A role is just a convenient way to group up sets of permissions. This makes it simple and easy to give people sets of access. All security schemes tend to boil down to the same thing: For an effective user The system has something to secure. That "thing" needs an identifier, so your code can bridge between the abstract idea of "I want to secure one or more features, functions" and a way of representing those things in your code. Once you start to group those individual things together, a role is simply a parent grouper for a set of permissions By giving a "user" one or more roles, you give them the access appropriate for the role(s) you want them to have There is nothing more or less than that involved. It also points out that roles are more than just a relational concept, but can also have meaning that can short cut granular permissions. In some cases (Symfony 5/6 for example) which you mentioned, there really aren't any granular permissions. You have roles (and again a user can have one or more roles) and you use roles specifically in controllers or methods. The problem of user authentication is intrinsically separated and solved for you, but after a user has been authenticated, you use roles in various ways to write whatever security code you might need. To handle more complicated scenarios like the ones you brought up in your use case, you utilize voters. Custom voters basically let you write the type of complicated access code you might have that involves row level access to things. Their documentation covers scenarios for a blog/forum system like: For a post If I'm the owner I can see it If I have the "admin" role I can see it If It's public anyone can see it Since you already mentioned you are using some portions of symfony, then I would highly recommend looking through the security documentation, and paying special attention to the "Access Control" and discussion of voters and custom voters. It also has an event system, which lets you write hooks for specific security events that can be very useful in dealing with many scenarios (login, logout, user changes password, unsuccessful login attempts etc.) From what I understand of what your requirements are, there isn't anything that can't be done with a higher degree of simplicity and elegance, using the current symfony security scheme. The voters give you a way of handling the things that pure roles can't. The main exercise for you would be to devise a role system that matches what you require. Keep in mind that with this sort of system, you don't want or need something like "read", "write" etc, because you are going to secure those individual routes or class methods. You won't have an abstract token to represent those ideas, and one could argue that trying to use a file system oriented access scheme isn't appropriate to data anyways, so trying to borrow those concepts isn't a good juxtaposition.
  3. From what I interpret from your first reply, here is what I think could be helpful. Relational databases have no concept of inheritance/super/sublcasses. So when you have OOP code that clearly benefits from inheritance, and you are persisting data in a relational database, you are left with 3 choices: Put all the attributes in one table/set of tables even though there will be a handful of attributes that are only relevant for a subtype. The more subtypes you have, the more of these irrelevant attributes, and to compound this, you have to name them all in some way Create a full set of separate table(s) for each type Use the supertype/subtype model There is nothing special in SQL that makes this relational design pattern work. You have a type field in the supertype that indicates which subtype of user this is The relationship between supertype and subtype is 1-1, and thus the subtype has the same primary key as the supertype. This is what is described in the article It is what your model implemented with supertype user, and subytpes (vendor_user, tenant_user) -- typed by user.type value/field You or your ORM need enhanced capabilities beyond the basic one-to-many, many-to-one, etc built ins. You will have in essence some switch statement type logic in your model to handle the subtypes I won't talk about the first 2 options, other than in comparison of some benefits that supertype/subtype can have. A typical requirement would be in storing contact methods for a user. Let's say that you have these contact methods: (phone, email, address) and each of these can exist as multiple types (home, work, mobile, cell) and perhaps you will have a primary designation. A lot more about this problem is covered by an implementation of the "party pattern", by which I refer specifically to a relational structure. Another common requirement would be in relating users together in some way. An example is a hierarchy for Company -> Department -> Employee. Just to simplify, let's say you implement this with a many to many resolution of employee to employee, typically with a "relationshipType" attribute to give context to the values. Just for simplicity, I'll provide these relationship types ("parent of", "spouse of"). Here is where the benefits start to add up. You create these tables and code that lets you add (for an employee) one or more addresses, one or more emails, one or more phone numbers. This code works for all subtypes. You are not duplicating database structure. Your query capabilities are more rich (I have this phone number, who/what is it for?) You query one table for that, vs, if you have tables for each subtype, you have to query the phone number table for each type of employee. You can relate subtypes together again using one relational structure. Following this, and looking at the party pattern, if you step back from employee, and instead make the supertype "entity" where an entity can be any of (a person, a user, a company, a department, a subsidiary, a customer etc.) you get more and more flexibility with your structure, and you still have a way to map between your classes and your relational store. You are still going to use composition and Dependency Injection etc. but you also have a nucleus of tables that support your data persistence requirements and you will be reusing more code and structure. Now in terms of Laravel and Symfony, both ORM's have capabilities that support the supertype/subtype relationship. You may or may not find those facilities useful, or better yet, performant to an acceptable level for you, but they exist and can be used. Yes this is a common pattern used by data architects. It's not found much in garden variety systems, although to be fair those type of systems either don't have complex requirements or the people designing the database aren't experienced with relational database design in general. So to conclude, you have already got a model that uses this pattern, in the case of your user table and subtypes. I assume that the reason you were doing that is that you'd already concluded there were benefits in terms of attaching things like security, which will require relating security to users across types.
  4. In most relational design parlance you call this "subtype" or "subtyping" and refer to the base table as a "supertype". There is a symbol that ERD tools use for this type of relationship, as shown in this article: https://learndatamodeling.com/blog/supertype-and-subtype/ It's the half circle connector they show. Ultimately, it resolves in the same way you resolved it for those tables, but my initial take on what you are doing is: Not sure why tenant_user and vendor_user both have tenant_id and public_id. If there are a bunch more specific attributes only pertinent to the type, then that's where they would go. Right now I don't see the value of the subtype tables at all. You have a bunch of attributes that smell like repeating groups tenant_default_permission vendor_default_permission or tenant_read_permission vendor_read_permission I would return to the question of "Is there an entirely generic ACL structure that can do what i need?" Obviously there is, because people have used generic ACL/security systems for years to support complicated business security concepts. I don't really buy into your "reinvent the wheel" approach. The other thing that is notoriously problematic, is when you have a mixture of static permissions and row level permissions. It means that you can't do a single query without baking that into everything you do. Some years ago I worked for a startup that implemented a full social media system, not unlike facebook, but with more sophisticated access control and permissions of things. The primary insight for me, was that "entity groups" was the mechanism that facilitated and solved a lot of problems. By having groups that related users and organizations to each other, and groups to each other, every piece of content or digital asset could be controlled by belonging to one or more groups. Rather than a single person entity owning a file, a group owned the file, with the original creator being the only member of the "owner" group. Through the creation of different groups with separate "group type" it was always possible to join to content and determine if that should be in a relational result or not. This is just an aside, but it's what I thought about when seeing how you are attempting to solve a few different problems. "Do I have access to this feature or function?" is one problem that ACL is built for. What content should I see based on my place within an organization or department, is another problem. ACL's are not well suited to the 2nd problem, and it looks to me like you are trying to solve both problems with a hybrid/relational structure, and that's jamming a square peg into a round hole if it's too much of one thing or another.
  5. It really depends on your markup. Another solution would be to render the data back into a form, perhaps with the original form elements set as read only. The important thing to note, is that with html, whitespace is not preserved. There is an expectation that markup will be used for formatting, and thus, the idea that a bunch of text with newlines in it, means there are separate paragraphs, is not a concept that exists in html. You can use nl2br as Barand suggested, but it's not that great a solution. It basically just replaces newline characters in the original text with '<br>' characters. A more robust solution would be to use explode in combination with something like trim to derive paragraph blocks and then render them using actual paragraph tags. This gives you much better control of the re-formatting of content. PHP has the explode function which makes this fairly easy to construct. Something along the lines of this could also be a solution: <?php // Original Text in a variable named $content function makeParagraphs($content, $cssClass='') { $content = explode(PHP_EOL, $content); $output = ''; $p = $cssClass ? '<p class="' . $cssClass . '">' : '<p>'; foreach ($content as $paragraph) { $paragraph = trim($paragraph); if (!empty($paragraph)) { $output .= $p . $paragraph . '</p>' . PHP_EOL; } } return $output; } I'm not a huge fan of this type of function for generating html output to be honest, as I try and always separate markup from data, but it gives you an idea of what a function like this could be used for, and problems it can solve for you. Most of my code utilizes a templating system (twig or laravel blade), so I wouldn't have written a function like this, but instead would probably do something more like this, if I was going to only utilize PHP built in templating: function makeParagraphs($content) { return array_filter(explode(PHP_EOL, $content), function($p) { return !empty(trim($p)); }); } ?> <?php foreach(makeParagraphs($content) as $paragraph): ?> <p class="largeText blue"><?= $paragraph ?></p> <?php endforeach ?>
  6. I've not following along too closely on this long and convoluted journey, but the obvious answer is that the derivation of the $chk variable (which is probably erroneous given that you check a variable you create outside a loop that seems to be a related part of the $table array) has absolutely nothing to do with how many checkboxes you have. Your code should output a checkbox for every row in $table. One thing that might be problematic in your markup, is the lack of a space between the value attribute and the word 'checked'. That has nothing to do with why you don't have more checkboxes, but I'd still fix it like this: foreach($table as $id => $arr) { $chk = in_array($id, $Vehicle ?? []) ? ' checked' : ''; echo "<label class='boxstyle'><input type='checkbox' name='vehicle[]' value='$id'$chk>{$arr['VehSelection']}</label><br>\n"; }
  7. We don't really need your entire project, but the answer would be to put it up in a github repo, and provide people a link to that. If there are any credentials in config files, make sure you remove those, if you go that route. With that said, it appears that the problem is concentrated in the email sending portion of things. Getting emails to be sent properly is a non-trivial system administration exercise. Post the class and implementation code that actually sends the email, so we have a better idea of what that is. Are you using an smtp class? Do you have a local/workstation version of the app, and have you tested it locally using a mail trap like mailhog? This is the modern way to work on an app and allows you to ascertain whether your issues are code based, or mail configuration based This is an incredibly common issue, and 98% of the time, the code is correct, but there is some hosting issue or relaying issue preventing email from being sent or handed off.
  8. You were advised to use the code tags before you even posted any code. Now you have made 2 posts and didn't use the code tag button to input your code. Why is that? You said you changed things as advised. What exactly did you change? You commented out two settings that have nothing to do with your problem. Where is this code? Is it in a function or file that is being included? It appears to be code in a function, because you inject a global variable into function scope "global $config". This suggests that you have a function that you are then including or calling somehow, but you only provided this snippet of code, which gives no context to what you are doing. If you "did what was advised" then why are you still using ob_start()??? Do you know what ob_start() does and what it is for? You are wasting everyone's time by providing parts of your code, and not following directions. The error indicates that your code is starting a session before the session_set_cookie_params() call is made. I'm going to guess that this is because you are providing a small piece of your actual code, and the problem won't be found in the 7 lines of code you cherry picked.
  9. Putting the vhosts into separate conf files is an option. It's not a necessity. In your original file i saw this mismatch: DocumentRoot /var/www/foxclone/public_html <Directory /var/www/public_html> You declare the docroot to be /var/www/foxclone/public_html but then your Directory doesn't match that. See the issue? In order for an index.php to be the default file loaded you need a DirectoryIndex index.php Somewhere in the loading of files. One other thing that can cause issues is that the user that apache is running as, needs at very least "rx" permissions to directories, and "r" perms for the files. It doesn't matter if they get those permissions as owner,group or other, although it's best practice not to use "other" perms. Typically your apache process is going to be configured to run as "apache". You can do a quick check from a shell using "ps aux | grep http"
  10. Do you realize that the SSL configuration for radproducts.com is incorrect/broken?
  11. Is that your actual html page? Where is your doctype? Like Requinix stated, the 1st thing you should be doing is using your browser development tools to investigate. In particular the javascript console, network tab, and perhaps the sources, in order to debug your javascript if some obvious problem doesn't jump out at you before you get to that point. Since you rely on ajax, the network tab is where you can actually debug the data loading.
  12. No worries. To answer your question, typically apache's main config file will load files in one or two other directories. Some linux distros have schemes for turning vhosts on/off via symlinks from one directory to another. It really depends on your OS/Linux distro and the defaults. Reading through the conf files is worth doing. The general best practice is to put each vhost in its own conf file. You also want to have each virtual host site in its own directory, and not have any nesting. In other words Do this: /var/www/site1 /var/www/site2 Don't do this: /var/www/site1 /var/www/site1/site2 Really, the best practice for php projects is to do this: /var/www/site1/public <- set webroot to this for site1. /var/www/site2/public <- webroot for site2 This allows you to have other directories with php files in them that you want to include, but can't be directly accessed via a url. Things like config files, class definitions, function libraries etc. can all be kept out of webspace, but are still available by scripts in or beneath site1/public.
  13. If you step back from the minutae for a second and look at what your code is doing: if ('delete' === $table->current_action()) { $message = '<p>' . sprintf(__('Notifications deleted: %d', 'prg_customer_notification'), count($_REQUEST['id'])) . '</p>'; } This has an implicit assumption built into it: so long as the current_action() result is the string 'delete' then you assume that there was notifications deleted. What if there were no notifications deleted, or the list to be deleted was empty? So how could you fairly easily fix this issue, where you need to be sure that there is a reason to display this message, while also providing additional feedback to the UI? if ('delete' === $table->current_action()) { if (!empty($_REQUEST['id']) && is_array($_REQUEST['id'])) { $message = '<p>' . sprintf(__('Notifications deleted: %d', 'prg_customer_notification'), count($_REQUEST['id'])) . '</p>'; } else { $message = '<p>Nothing to delete.</p>'; } }
  14. The servername needs to be a domain name -- something that the DNS of your workstation can resolve. What you want to do is use an appropriate top level domain (ie. .com, .net etc) for testing, and set that up in your hosts file on your workstation. The IETF set aside a number of development tld's, and of these you should use either .test or .example. You should avoid using .localhost even though that is also reserved, just in case you get some loopback conflict. so what I'd suggest is that you add something like this in your /etc/hosts 127.0.0.1 www.project1.test 127.0.0.1 www.project2.test It doesn't matter what project1 or project2 actually is. One argument in favor of using one domain like (projects.test), is that you can setup a local SSL cert on your machine, and use that for multiple projects. You would then use www.projects.test, cms.projects.test, admin.projects.test or whatever else makes sense for your development work. It doesn't matter how you do it, so long as it works for you. In this example, I will stay with the 2 separate domains example. Here is the apache vhosts config you would want: <Directory /> AllowOverride None </Directory> <VirtualHost *:80> ServerAdmin webmaster@test ServerName www.project1.test DocumentRoot /var/www/public_html <Directory /var/www/public_html> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog /var/log/apache2/project1-error.log LogLevel error CustomLog /var/log/apache2/project1-access.log combined </VirtualHost> <VirtualHost *:80> ServerAdmin webmaster@test ServerName www.project2.test DocumentRoot /var/www/test/public_html <Directory /var/www/test/public_html> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog /var/log/apache2/project2-error.log LogLevel error CustomLog /var/log/apache2/project2-access.log combined </VirtualHost> Notice that I fixed the Directory statements for each of your vhosts. These refer to the directory structure of your server, so you can't redefine those perms, as they aren't relative to a specific vhost. Apache starts out with (or should, depending on your OS/Distribution) a definition of <Directory />AllowOverride None</Directory> as a way of blacklisting the entire directory structure by default. You are then meant to override specific directories from which you are actually serving content. Usually this type of configuration is set so that you can/will have a .htaccess file in the root of your project directory that you will use for things like mod_rewrite rules.
  15. If you joined the discord and had an issue getting access to the channels, PM me here, or any of Zane, requinix or myself in Discord and we can get your status fixed.
  16. Well these are a series of functions. Do you have a function that checks for the AD security group membership? You should build one around the PHP LDAP functions. I don't know if you already know this, or you are asking how to query AD, you need to use the LDAP library. Since there is a variety of different ways to set up groups in AD, you'll have to figure out what is appropriate for your system. I haven't done this in a very long time, but it's good to use an LDAP query tool to figure out what queries return what you expect. This Stackoverflow question is old, but it should give you an idea of how to attack the problem: https://stackoverflow.com/questions/23270575/validate-ad-group-membership-with-php-and-ldap Assuming you had such a function, simply adding an additional check should do the trick. I would rewrite this function in this way for clarity and efficiency: function check_australian_access($hide) { global $user_details; require_once '/var/www/common/emailer.php'; if (!$hide || (is_australian_server() && is_ad_member('ALLOWED'))) { return; } // Shouldn't be able to see this print "<b>This information is restricted to users of COMPANY, located within the Australian network.<br> <br> This access attempt has been logged.</b> <br><br> IP Address: $_SERVER[REMOTE_ADDR]<br> Username: $user_details->username"; email_from_to('SYETEM <fromaddress@company.com>', 'toaddress1@company.com,toaddress2@company.com', "Illegal Access Attempt - $_SERVER[REMOTE_ADDR] - $user_details->username", "An unauthorized user has attempted to access restricted information.\n\nURL: $_SERVER[REQUEST_URI]\n\n" . print_r($_SESSION, true) . "\n\n$_SERVER[HTTP_USER_AGENT]"); exit(); }
  17. There is some variation in regards to the palette extraction. I used the picture from your mockup. There is very little difference between the one you have and the one I added. The order of the colors is not important either. If you like the mocks I posted, use the colors I posted, or use the ones you posted. You're going to get similar results with either palette. My inclination is that I would use the brown for the background, the muddy green for the menu and bottom bar, and the tan for panels. With tan for panels, you can use the brown for your text inside the panels as in the mocks, and you can also the darker green for another panel type if you want variety.
  18. It's a class that can be iterated with foreach. It is not an array, but it has many eloquent specific capabilities you can read about here: https://laravel.com/docs/9.x/eloquent-collections. For example it has a method that will return all the primary key values of all the models in the collection. Keep in mind that it extends the Laravel collection base class, which has many more methods that might be useful depending on what you want to do. See https://laravel.com/docs/9.x/collections
  19. Seems like you ought to buy Barand a cup of coffee at least
  20. Yes definite improvement. Don't use any colors that aren't in your palette other than black or white, which are neutral and sometimes necessary for legibility and accessibility. The ugly yellow color that seems to persist in the menus needs to go. You have the option of making the top menu black with white or off-white lettering, or going with a color combo from your palette. I'd also suggest taking a look at fontawesome and trying to find some icons that you can use to accent your sections. The mockup has examples that should give you some ideas. You want to find an icon for each section that visually illustrates what the section text is saying. I extracted a palette from your image and applied it to colormind.io, which has a nice prototype screen showing you different ways the palette could be assembled. My advice would be to use some of the darker or lighter shades of the palette, and then use the green for your windows. The mockup here should help you get a better idea of what you like. The top is the color palette. You then have a summary, that also works to show you what a light overall background color for your site would look like. The next section is what a dark color background would look like. I would suggest you start with that. I also provided the "Dark on light" mockup. I'd suggest trying the "main brand color" #8c8f38 color for your menu and footer background.
  21. What you are doing is very confusing. Why are you not extending from the \PDF_Code128 class? Do you need the features of that class or not? Having code that both defines a class and also creates objects of that class is terrible. Have your class definition in a script with the name of the class as the name of the script. Then require that class in your script. As for the problem, it's shown to you clearly in the stack trace. You need to actually learn to look at it and follow it. FPDF is throwing the "No page has been added yet". You need to determine where in your code, that exception is occurring. The stack trace shows you that: $barcode = $pdf->Code128( 4,3,$data['item_code'],30,10); So this is the code that triggered your error -- and it's an object you try and create, purely so you can pass it into your class, yet don't even use in your code.
  22. The plugin issue is just a theory. I have no experience with XenForo, so all I can offer is an educated guess. If the person had some sort of axe to grind with the forum, then I guess that could be the case, but I thought that you moved things to a new server, so perhaps there is a separate installation for plugins that needed to be done.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.