Jump to content

gizmola

Administrators
  • Posts

    5,945
  • Joined

  • Last visited

  • Days Won

    145

Everything posted by gizmola

  1. And what do you plan to do with the survey?
  2. This is database design terminology. A relation is the connection between 2 tables. In a relational database there is no such thing as a subtype. You can support the idea by having something like product_type, where the various subtypes you want to support are enumerated. Then for every subtype, you need a table. So in your case, the one we know about is "membership". Let's say that Product.type can have these values: Article Membership Clothing Then you would expect to have these tables: Product_article Product_membership Product_clothing You make a dependent relationship between Product and the subtype table, so that it's primary key is the same as the Product primary key. The "type" column in Product indicates which subtype table you would expect needed to be joined to. ORM's like Doctrine2 and Laravel Eloquent have a degree of support for this. Pricing should not be related to the subtype table, but instead be related to the Parent product table. When a membership is ordered, you would have the Product linked to the order, not the subtype table. There are practical reasons for designing things this way. I can't write a full relational database design treatise on these design patterns or why they work and are maintainable, database driven and easy to code for. I don't think that's fancy. I'd probably have an attribute in the Product_membership subtype table that could be as simple as a flag that indicates "plan_can_be_renewed" or something like that. Again the aging logic of plan renewals would take this into account when the logic runs to offer the member a renewal. This would really be the reward for the pain of engineering around a subtype table schema which defies standard sql joining of tables. Overall, it seems that most of your tables are just named in a way that is specific to your ideas about how you plan to implement memberships. Hopefully I've headed you off a mistake in regards to Product and Member_plan. The way to think of member_plan is that it's a home for those things that are specific to a membership. As I mentioned I wouldn't name it the way you are planning to name it. It should be named conventionally to indicate the product type as I explained above. I would probably tell you to use common relational design patterns. I'd also point out places where you are not normalizing. I've done much more database design work as a system architect than most people, so I have a lot of experience with relational design patterns and understand the limitations and implications of a series of tables. Your tables (albeit with some different naming) seem to be close to what I'd assume you would need for a system like this, with the main issue being what appears to me to be a misunderstanding of relational subtyping. Even with that, you absolutely would expect to have an order for a membership with a lineitem for that membership with the foreign key to the product, and the price paid in the lineitem + tax if applicable. Nothing should go into Product_membership that isn't entirely specific to memberships. Things that should be in Product and not in membership would include status (active, inactive, deleted), category_id, name, description, manufacturer id, taxability, etc. Also as I mentioned previously, I'd expect that there would be a price table related to Product, with the price and from_to dates. In this case I would severely question the need for a subtype table extension, if there is only an attribute or 2 specific to membership. If it's only going to be "duration" and "can_be_renewed" flag, I don't think I'd bother. I'd just stick a couple of extra columns in Product.
  3. IPV6 is a 128 bit number, broken for representation into 8 16 bit blocks. Since each byte requires 2 hex digits, a 16 bit block requires 4 hex chars. This range of numbers has 2 issues I see: Only 6 blocks. Some of the 6 bocks have only 1 hex digit. It is ok to omit "continguous" zero blocks, and replace them with '::'. This is the most confusing part of ipv6, because it doesn't matter how many contiguous '0000' blocks you have. It can be 2,3,4 etc. You can only use that trick one time however in a number. ipv6 parsing figures this out and expands the '::' to the correct number of zero blocks. Thus the example #967 is invalid because there are only 5 blocks. 2a04:4540:8202:ce00:7c50: This would be valid 2a04:4540:8202:ce00:7c50:: # Is actually equivalent to 2a04:4540:8202:ce00:7c50:0000:0000:0000 See if something is messed up that is stripping off an ending '::' and reducing it to ':' ipv6 numbering supports "zero suppression" in a few ways. You can remove leading zeros OR you can compress 4 zeros into one, OR you can omit a block of zeros (one time, I think) in a number as per the example above. So testing #757, again we have only 6 groups, when we need 8, so once again, adding an end '::' will make it valid: 2a02:0c7f:1804:b000:4970:6:: #Equivalent to 2a02:0c7f:1804:b000:4970:0006:0000:0000
  4. I would want to see an ERD of the tables involved in this question. If order and subscription_details have no relationship to each other, then why do you have them both? A typical commerce system would at minimum have: Order --< lineitem This allows people to purchase multiple things in one order. The usual way this might be handled would be to have an item that describes the thing being purchased. So the extended model including lineitem: Order --< lineitem >-- Item Items I would expect: 1 Month Subscription 3 Month Subscription 6 Month Subscription 12 Month Subscription 2 Year Subscription Each of these will have a price, although the price usually would be in a seperate table related to item, broken out with an effective from-to date. So in conclusion, it looks like your subscription_plan = lineitem (although not generically capable of supporting sale of things other than subscriptions) and plan = item. I'm not sure why you are making this so specific to only subscriptions, nor am I clear how order fits into this. Having a lineitem date would be unusual in a system like this. If I order a stick of gum and a magazine on tuesday, I don't need a separate stick of gum date & magazine date, which is going to be the same as the order date. Renewals is an aging process in subscription systems. You run batch processes that do things like: -send out 1 month reminder -send out 15 days reminder -send out discount offers send out expiration notice -send out churn offers (come back and I'll offer you 10% off) etc. These operations don't require an end date. What they do require is a start date, and the subscription status and duration.
  5. Yes, it's a language construct that is part of javascript itself. One essential resource is Can I use? Very nice way of checking if the techniques
  6. In case you were wondering, the example provided is the implementation of an IFFE (I pronounce it IFFY but maybe that's just me). A very useful mechanic and design pattern. Once you grok it, you will find it very useful. To quote the page I linked: You may find yourself looking at all the global variables and functions you made to and finding this technique a great way of cutting down on those.
  7. I'm not sure what you are after there. Those are simply environment variables from the server running php. What is your server stack? Are you running IIS, Apache? What is the OS of the server? You stated that you have a simple login. What I've done in the past, is to have the login make LDAP calls to active directory to authenticate the user. Before you go down the LDAP road, If you are lucky and your environment intrinsically supports this, you could try to echo this value: echo "Current User is {$_SERVER['AUTH_USER']}";
  8. Lately I've been getting real annoyed with SO and some of the stupidity that goes on there. As it happens, I stumbled upon the author of the PhpDelusions PDO and MySqli tutorials SO profile, and discovered that he/she had been banned from SO apparently due to too many complaints from the clueless he's tried tirelessly to educate. SO Profile here. Had 146k rep, over 4 years and Hundreds of answers on php, pdo and mysqli. I know many if not all of the admins, mods and gurus have linked people to phpdelusions in the past. The old adage "no good deed goes unpunished" seems applicable.
  9. Yes, you can make LDAP calls in php, to your AD. That would likely be the way I would do it from what little you've said. AD is compliant with LDAP.
  10. You bootstrap requires routing. Essentially routing is the piece that takes a url and matches it to a controller. Some examples to look at: https://symfony.com/doc/current/routing.html https://laravel.com/docs/7.x/routing https://book.cakephp.org/3/en/development/routing.html There's lots of Routing components/classes out there, but here is one that might make for a good model for you: https://altorouter.com/
  11. It seems from your logs you are close though.
  12. I am not great at that either. I have 2 2015 Macbook Pros I use, both on Mojave, but I have decided not to try and upgrade them to Catalina, as I read that it broke a bunch of 16bit apps, and I don't want to spend time or money trying to upgrade things that currently work fine for me. The main thing I am wondering about is that you are starting up a cli app, and there are some other vsc settings that might be relevant to the cli like: program: Path to the script that should be launched args: Arguments passed to the script cwd: The current working directory to use when launching the script runtimeExecutable: Path to the PHP binary used for launching the script. By default the one on the PATH. runtimeArgs: Additional arguments to pass to the PHP binary externalConsole: Launches the script in an external console window instead of the debug console (default: false) env: Environment variables to pass to the script
  13. It's fairly obvious I think. Your $text variable has single quotes in it. You are then trying to insert it: $db->query("INSERT INTO gangevents VALUES(...,'$text')"); Because you are not escaping the $text, you have conflicting single quotes because at runtime the $csscode... becomes: viewuser.php?u=666' id='member' Notice the single quotes around 'member'. Really you should be changing all your code to use parameters. That is a countermeasure for SQL injection exploits AND eliminates the need for you to escape input. But in the near term you could fix this by making sure that the code that generates id='member' instead generates id="member"
  14. The Rewrite looks fine to me. Oops, yeah should be (list|gallery) For aliasing I would suggest that rather than using rewrite, use mod_alias with the alias_match directive
  15. Maxxd is right. You should never do this, but it's a common mistake that is hard to recover from unfortunately. You should always store datetime values as UTC, and this should be the timezone of the server OS, php and mysql. Once you know it's in UTC, you convert the date using a timezone for the purposes of display.
  16. This is one of the reasons I don't use bactics around column names unless they are absolutely necessary (wihich is rare). $query = "UPDATE greencard SET comments = '$comments', sent = '$sent' WHERE hospitalnumber = '$hospitalnumber' and PIN= '$PIN'"; Make sure that follow Requinix's instructions and change this code to use parameters and prepared statements. There is no excuse to write new code this way!
  17. This thread has already gotten really long winded so I'll try and conclude with some final cherry picked replies: PCI Compliance If you have a server in the cloud you simply can't be PCI compliant. You aren't really allowed to handle credit card data yourself -- but instead utilize the payment processor. This essentially reduces your concerns at the PCI Level 4 merchant level (or below) to doing a self assessment document. All you get from a payment processor, and will be allowed to store and use subsequently is tokens. Tokens aren't hashes either -- but are instead single use (nonce) keys that let you interact with the payment processor. At any point along the way if you are storing the original credit card input, you are at risk of running afoul of pci dss which you don't want. You can't store the cc info, even temporarily in a session variable to make the form process work nicely. This is one of the reasons that just about every modern payment process has a final step where the payment information is dealt with separately, and why the cc info is not retained between calls to the gateway. You wrote about how you would do subscriptions without doing subscriptions, which basically means that you will have to start messaging people about their pending renewal, and when it gets around that time, you will need to do a new transaction where they enter all their payment info again as if it was the first time. You kind of positioned this as a badge of honor, but it's a really poor decision for a subscription reliant business. I literally have never seen a single subscription business that involves that design. The hash in support of the ban tool You could go ahead and do what we've discussed, and take a piece of the cc# along with other pieces of name and address and make a hash and store it. You could also check against your own table of fraudulent credit cards and intercept a potential transaction before its sent to the gateway for that matter. You just can't store any of the inputs being provided to you persistently. Is a hash based on a piece of a cc# useful? Numerous people have pointed out the same issue, which is that people can have lots of different cc and cc#'s. The thing that Requinix described is not some esoteric product, but offered by large banks like Citibank, Capital One and Apple (backed by Goldman Sacks) to name just a few. It lets a customer go in and generate a disposable card#, ccid and expiration to be used for one or more transactions online. It's existence entirely defeats your hash. In fact it suggests that adding in any part of a cc# makes the hash less effective. Given these facts, assume you go ahead with your original idea. How will you create this table of "bad hashes" in the 1st place? Are you going to make a hash for every paid user stored with a flag that is 'ok' and then flip that to 'banned' or something like that? If that's the case then you would have with sha1 for example, to store a 40 character string in your database for every single user, just so that you can flip that on a handful of users at some future time. That's a lot of storage for something that would be used infrequently. Is a billing address required for ecommerce? I can only answer this technically having implemented e commerce numerous times with different vendors. With some of the largest payment processors in the marketplace, the address is not part of the input to the gateway. You may do with that what you will, but again, if I'm not shipping you anything then what do I need your address for? I brought up the gas station example, and your reply was that the card was present. That is true, but why then are they asking for the zipcode? It is because the card could have been lost or stolen. It's just an additional check. With ecommerce, the entry of the ccid is the equivalent mechanic that validates the card is present. You should also know that credit card fraud is *your problem*. Most of the payment processors offer their own fraud prevention services that you can pay for or not. There is no built in visa/mastercard/amex/discover fraud prevention system you just get automagically. Fraud = chargebacks, and chargebacks are bad for your business and will cause your per transaction costs to go up, or can even lose you your merchant account. Payment tech is changing Younger people are using mobile payment tech like apple pay, google pay, samsung pay etc. There is also a long tradition of alternative payment options, with the most prevalent being Paypal. Most people that take payments are going to support paypal, and you might also like to support these newer technologies at some point, and none of them have credit card #'s. Legalities There is a lot of state and federal consumer law out there. Just because you put something in a TOS that takes away someone's rights doesn't mean that will stand up in court. My final word If you want to do what you originally brought up, then technically it can be done. Requinix wouldn't if it was his company, and I wouldn't if it was mine. I just don't think it would be worth the time, effort, and storage cost, even though it could be coded up relatively quickly by someone who understood all the parts and technologies well. Furthermore, if I wasn't stuck in my house right now, I doubt seriously I would have continued to engage in this conversation given the mysterious nature of your proposed business. I don't want nor need to know what it's about, but I just have my doubts that there is any online community that people will pay for, when there are numerous well established online communities out there that are free. Usually the devil is in the details for any online business, and it's just not very fun or interesting to tech people to try and guess about what feature might help you enforce rules, without understanding the game afoot. Get your MVP up and running and then if you want, you can come back armed with specifics and actual real customers, and you'll find people a lot more enthused about your ideas, whether they be viable or not.
  18. When I stated you don't need a billing address for a cc transaction that is because it is not input that is checked, thus it is optional. Consider how cc's work in the world. When you go to buy some gas for your car at the pump and insert the card, do they make you type in your billing address? Consider the many ways that the same address can be entered. Any matching that might be done on address would be fuzzy at best. Again even with the same address (and I'll assume you would uppercase the input, because any variation of even letter case generates a different hash) I can vary my input slightly to get around your mechanic some number of times. Bob Smith 232 River View Lane Grand Rapids, MI 83293 Robert Smith 232 River View Ln Grand Rapids, MI 83293 Robert Smith 232 River View Grand Rapids, MI 83293-3233 Robert Smith 232 River VW Grand Rapids, MI 83293-3233 Now I don't think people are going to do this to try and get around your system. Quite frankly I don't think any legit user who you just banned (and I would think you would need to probably refund at least the remaining portion of their fee or likely face legal challenges) is going to turn around and try to sign right back up again. Won't happen, so what is the point of creating a complicated and tempermental feature that isn't actually going to stop anyone who is persistent from resubscribing? As we've already established, all they would have to do is just use a different cc#. That's not reverse engineering anything. That is using intimate knowledge of system internals + a person's name, which in this scenario we are assuming your whole system database got dumped. Yes it would be trivial for me to create a rainbow table of 10000 entries for every name in your database, all so that I could establish? The last 4 digits of an unknown credit card? Now let's say that they got hold of this table or column of hashes with no idea what they were used for. Can they be "reverse engineered?" No. Someone could try and generate a collision value, but that has no value in this use case. It's just another set of input that will generate the same hash (or the original input, although if created randomly, the person running the computation wouldn't know). If you wanted a larger hash, you could jump up to sha256, but that sort of decision ought to be made because you fully understood at least at a layman's level, how the hash works, what the pros and cons of it are. At this point, the only reason I'm continuing to elaborate is to hopefully incent you to spend some time researching these things yourself. This is the reality -- if your system is so deeply compromised that all the data and source code and key values and salts you might be employing are known to them, they likely have full control of your entire infrastructure and can just siphon off all of your transaction data in real time or shut your system down, encrypt all your data and hold you hostage.
  19. I assume from these questions that you are on shared hosting? Since you want this processing to take place for any requests that might be coming in, I would place it at the top of your htaccess and see if it works or not. You don't want to manually code in ob_gzhandler() calls for your pages if you can have apache take care of it for you. Ideally, you just want the configuration to be serverwide or at very least vhost wide, but perhaps that isn't possible for you, so in that case a htaccess statement at the root of your site would be preferable.
  20. This is a well articulated explanation of the point I was trying to make earlier about making things overly tough for the paying customers you want (the 99.5%) in order to police and provide barriers for the .5% you don't want. History has shown that this is a bad business model. You have to be very careful about alienating the customers you want. If we once again return to the questions you've posed about "security", for your purposes a hash is secure. You can not take a hash and determine what the input was that created that hash. md5 and sha1 are often used for fingerprinting of things to determine if they've been tampered with. A pdf document for example, uses sha1. In the bad old days people often used md5 and sha1 to store passwords, and what would happen is that if the system got compromised, perhaps through a sql injection issue, then the entire list of user account password hashes might be disclosed. In those days crackers would have pre-generated rainbow tables of all sorts of common words phrases and names that people would use in the bad old days. A quick check against the table for a large membership database, and I might find 10% of the users had bad passwords that matched hashes in a rainbow table. Those crackers could then, perhaps with an email address in hand, try the same password on other systems, and people being naive as they tend to be, often reuse the same password across systems. In more recent times supercomputers and high performance gpu clusters have proven to be able to do incredible numbers of hash calculations per second, so they can attempt to compute enough hash values to find a hash collision. This is not knowing the original input, but rather crafting some input that computes to the same hash value. I don't need to know the original password, but I have something just as good, which is a password that will still match. For this reason, people have stopped using md5 and sha1 as computed password values, and the industry has moved to techniques that are slow to compute. None of this is relevant to the use case you prevented of having a fingerprint value computed from portions of a user's personal information. So if you were to take a bunch of input (name, address, partial cc#) and hash it with sha1 or md5 along with some other input like a "salt" value, and store that in a database, you could use that later to see if some new user info matches a "banned" user. Yes you could do that. But can you reasonably expect to ask people for their full address for an online account when they aren't required? Unless you are shipping me a product, you don't need my address. What you need to get a payment from me is: -Name on the card -cc# -expiration -ccid -billing zipcode (usually for a higher level of fraud detection, but likely irrelevant for your online system). A lot of people are going to balk at giving you address information without an understanding of what you plan to do with it, knowing that you will store that information in your system and not do anything with it which just opens up the possibility that my personal information might be stolen from you at some point in the future. There's risk, but what is not clear to any of us, is what it is about your system that represents a reward substantial enough to pry information from a significant user base. You asked about how and why cc processing uses nonce values. It's exactly because as you already know, PCI compliance is expensive and out of reach of most businesses. It is simply a better work around to take input securely and pass that to the cc processor securely, who then issues you back a nonce for the transaction. The payment processor stores the cc details on their system, but you use the nonce they gave you to proceed with the rest of the payment process you need to eventually get a transfer of funds from the credit card issuing bank to your bank. In the US, given the way laws work that usually doesn't happen for 30 days anyways. You are not storing any personal cc info, and they don't want you to. In order to establish any recurring payment, you have to use a feature the payment processor provides to you where again, you will not store the cc# but they will on your behalf. Needless to say a lot of things can go wrong with recurring payments -- the card could be cancelled, it could lack funds at processing time, etc. etc. Lots of people are pretty savvy these days and have had bad experiences with services that they can't unsubscribe from, so again you better have something people really really want badly in order to sign up for a subscription. You could siphon off a portion of the cc# and store the last 4 digits, but I don't find that substantially more useful than the input you are already going to ask for, and at the end of the day it's a half measure that I can predict might catch a couple of people at most, and do nothing to deter anyone determined to get around this check, so at best it can only be one of many.
  21. Given your comments, I understand your concern. If you get to the point where your community is successful enough to have the issues you describe then you can pay people (or in some cases entice them to moderate for free) your community. This is how this forum works. The forum software does have tools that will blacklist emails and ip's, but neither of those are fool proof. They still make it an annoyance for anyone who has not automated signups. The average crackpot will simply move on. The other thing that we face like most sites with any significant user base, is attempts to spam or advertise. Again our small volunteer moderation group, along with the forum's ability for people to report posts they think violate our rules insures that we have almost no spam or abuse presence on the forum lasting for any significant amount of time. More often than not, if I see a report, it has already been handled by one of the other volunteers. Again, having too many users with some that won't follow the rules is a good problem to have. I simply happen to believe strongly that it's more important to concentrate on your MVP, and building your traffic and user base than it is to try and engineer a solution to a problem you don't yet have, when you haven't implemented the tried and true, if imperfect, controls that other sites utilize first.
  22. Just to go back to the original question, I'm not sure you are clear on what a hash actually is. A hash takes input and computes the hash. Hashes are not encryption with associated decryption. You can not decrypt a hash. They are also not part of php per se, but like most languages well known hash algorithms are available in php. Assuming you had a good use case for a hash, then md5 and sha1 are popular options. The more unique input you provide to the hash, the better it tends to be.
  23. Yes this idea is DOA. First of all, people are loathe in the modern era to provide identifying information. The less information you require to establish an account the better, if you want people to sign up. People provide information when they have an incentive to do so. A "community" where people won't join because it's too much of an annoyance to join will be a ghost town. In my experience it's hard enough to get people to pay for a service, even a well executed one that people use everyday. Before stackoverflow, there was experts exchange. It was once a thriving tech expertise community, then they tried to monetize it by obfuscating the content unless you paid. This really pissed a lot of people off, and the site went rapidly down hill until it eventually went bankrupt. SO was started partially in response to EE's poorly executed paywalling scheme, and the rest as they say is history. Candidly I have been asked many times over the years to come up with ways to prevent people from getting access to a system or to content. This goes back to days I worked in the gaming and entertainment industry. There are some interesting case studies as to the effects of over emphasizing piracy or restricting access to content they have paid for, and in every case the employ of those technologies harmed or hampered the business over time. Meanwhile competitors that wrote off the concern thrived and often overtook competitors that at one time were the market leaders with a huge competitive advantage. The harder you make things for your users/customers, the worse off the business will be over time.
  24. Yes the code is equivalent, but as ob_gzhandler() is a simplified shortcut, that would be preferred by just about anyone. Yes you can specify mod_deflate in an htaccess. <IfModule mod_deflate.c> <FilesMatch "\\.(js|css|html|htm|php|xml)$"> SetOutputFilter DEFLATE </FilesMatch> </IfModule> There are various analysis sites you can use to examine the output from your server like https://webpagetest.org/
×
×
  • 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.