Jump to content

NotionCommotion

Members
  • Posts

    2,446
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by NotionCommotion

  1. Yes, definitely needs to be cleaned up. Do not directly insert user provided values in the DB but use prepared statements. You don't want to use else if for all your validation but just an if since you are adding the errors to an array. You could shorten the script which assigns values by using $CONTACT_ID=$request['CONTACT_ID']??null; Break your code into several small functions.
  2. Are you positive that you are sending three requests? Or maybe some of the requests are not returning any results? Consider adding printf('$line: %s'.PHP_EOL, $line); write before you dump the results. Also a reality check printf('$textAr: %s'.PHP_EOL, json_encode($textAr); might not hurt.
  3. A while back, I was showed how to authenticate to PostgreSQL using peer authentication over a socket for applications where PHP, FPM, and PostgreSQL are all on the same machine. All works. I could use native PHP as shown and it returns results without errors so I know that PHP, FPM, and PostgreSQL is setup correctly to establish a connection using peer authentication without a PostgreSQL username or password. $pdo = new PDO("pgsql:dbname=testing"); $rs = $pdo->query('SELECT * FROM company')->fetchAll(); I could also use Doctrine but not Symfony and get results without errors so I know that Doctrine is capable of establishing a connection using peer authentication without a PostgreSQL username or password. $pdo = EntityManager::create(['driver' => 'pdo_pgsql','dbname' => 'testing'], Setup::createAnnotationMetadataConfiguration([__DIR__."/../src"], true, null, null, false))->getConnection(); $rs = $pdo->query('SELECT * FROM company')->fetchAll(); Now I am trying to do the same but when using Symfony. I expected I could just edit config/packages/doctrine.yaml as follows, however, it results in An exception occurred in driver: SQLSTATE[08006] [7] fe_sendauth: no password supplied doctrine: dbal: driver: pdo_pgsql dbname: testing server_version: 13 Any thoughts how to do this? Thank you
  4. Thanks gw1500se, /etc/ssh/sshd_config has AuthorizedKeysFile set to the typical .ssh/authorized_keys. But isn't this relative to the user's home? And I thought that system users typically didn't have a home. I didn't realize until now that when I create a new system user with the -r flag, /etc/passwd still shows it as having a home (i.e. my_user:x:983:979::/home/my_user:/bin/bash) even though there is no /home/my_user directory. Now that I am thinking about it, seems like if I want the user to be able to use ssh keys, I will need to create a home for it and the only decision is whether I want to locate it in /home or somewhere else and I might as well located in /home (agree?). I was first thinking there might have been something special regarding the postgresql user because I was getting the following, however, I have since discovered that the user was still created and I get the same warning for even user's which do have a home. I don't remember having this happen in the past but seems like a non-issue. $ sudo -u postgres createuser my_user could not change directory to "/home/michael": Permission denied man useradd -r, --system Create a system account. System users will be created with no aging information in /etc/shadow, and their numeric identifiers are chosen in the SYS_UID_MIN-SYS_UID_MAX range, defined in /etc/login.defs, instead of UID_MIN-UID_MAX (and their GID counterparts for the creation of groups). Note that useradd will not create a home directory for such a user, regardless of the default setting in /etc/login.defs (CREATE_HOME). You have to specify the -m options if you want a home directory for a system account to be created.
  5. I created a specific Linux user responsible to host a given site, created a postgresql user and database with the same name, and created a pool, and all is good... Almost. How can I make the user a system user (i.e. useradd -r my_user) without a home? Without a home, where should ssh keys go? Anything need to be changed when creating the postgresql user? Thanks
  6. I looked into ElastiCache. Looks like it is only available on AWS servers. Correct? Assuming so, looking for other options. I would like to have the redis DB saved on disk whenever the redis service is stopped or the server is rebooted. First started looked through /etc/redis.conf and read about snapshotting, but didn't seem applicable. Then looked at redis cluster (thinking it was similar to ElastiCache) but it is experimental and also don't think applicable. Next I did a reality check and stored a new value in redis and found that it persisted after both restarting the service and rebooting the server. I didn't expect this and was pleasantly surprised. Is it expected behavior for redis to save on disk? What is ElastiCache (or similar) doing and why is is required? Where is this functionally configured (I expect somehow using ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd and ExecStop=/usr/libexec/redis-shutdown located in /usr/lib/systemd/system/redis.service and some setting(s) in /etc/redis.conf but am not sure)? Thanks
  7. Finally was able to retrieve an authentication email sent my wife's email address (for unknown reasons, took a long time to be delivered). Emailed back to my primary use PC which is the only one I was able to logon to phpfreaks, and clicked the link. Then went to change my email but this time a QR code was displayed when being prompted for a code, and was able to change it. Then went to disable the f'ing authenticator and at first didn't realize which link should be used, and of course had to repeat the authenticator process each time but finally got it disable.
  8. Google Authenticator being a phone app? Maybe on a phone long ago. Installed it on my current phone and it is asking for a QR code or that I manually enter a setup key. Is this key a phpfreaks thing? Tried the other methods but none worked, and will try again later. Thanks
  9. The following is what I see when I try to log on from another device. Should I have received a code? Don't think I did. Messed around with Google authenticator but no success. Requested an email but didn't get one. While I still have some access to the email associated with my account, my wife stole it and I use a different email. On the machine I am using now, tried to change it but get these same prompts. Thanks
  10. No, I save only the last selected value. Potentially, I would have an lastUpdatedTimestamp property but would not store the history unless there were compelling audit trail reasons to do so but this is just for ux.
  11. Thanks maxxd, wasn't considering Redis. I should more often. I like how dealing with the life of the events is pretty much automatically taken care of by using TTL. Potential drawback will be lack of persistence upon restarting Redis, but will highly consider using Redis.
  12. Ah, wasn't thinking of saving each event in the DB. Seems excessive considering I don't really need the data other than for this purpose but data is cheap. Suppose I could get even tricker and do something like SUM(EXP( $const * (date_saved - NIX_TIMESTAMP()))).
  13. I originally thought of doing so but it sounds kind of tricky. How would you propose doing so? Not saying that my idea to cap maximum counts to some given value and to decrement other choices other than the chosen option is any easier, but at least I don't care about the start and end of some floating timeframe. Another thought which also isn't any easier is to save a timestamp with the ranking on a per user basis. Then when the user selects the same option the next time, the previous value is downgraded based on the time between the timestamp and present time and then upgraded based on it being selected. Probably a bad idea as I need to go though this whole process just to provide the choices...
  14. Yes. There might be 50 options but a typical user will often use the same choices as they had in the past so why make them sort through all the other choices which they don't want. If not the client, then who? An API server provides an array 50 objects which represent possible options and each object includes a name, identifier, and ranking property, and a web app or phone app needs to be written in order to present the choices to the user. Maybe my poor choice on terms, and did not mean to imply that the "client" was a HTTP client but some application that uses the data. My only goal is to present a limited number of choices which have high likelihood of being their desired choice, and believe that a usage counter is likely part of the solution. I don't think a simple counter will work as if someone's favorite colors used to be blue, green, and red, but then a year later it changed to yellow, purple, and brown, it would take a long time before their favorite colors become the most prominently displayed colors. Regarding "someone", these rankings are specific to a given user and the server will receive a request with includes the user ID.
  15. No, the ranking thing (AKA order) defines which options are most often used. The which-ones-to-display thing dictates whether to display the top 5 (etc) most common or potentially only those that have a ranking above a given value.
  16. I have several forms which will request the user to select one of several options where the most common choices will be pronounced, and might look something like: Select Option A Select Option B Select Option C Select Option D Click here for more choices The client is responsible to determine which ones to display (opposed to hiding within "more choices") and the server is responsible to provide the list of options along with some means to determine which ones are most common. For a new user, the order will be based on my "best guess", however, whenever a user selects a given option its ranking for that user only should go up, and in addition more recent activities should have more bearing on the returned order. In addition, there will be more than one of these lists and each of these lists will expose a public identifier (most will use a string but some might use an incrementing integer series) instead of the primary key. I have some fragmented ideas how to best implement but would like other people's thoughts on how to best do so. Starting with the list schema, undecided on which approach below. Any preferences or something else altogether? Solution 1: abstract_list - id (INT PK) - discriminator (string) - name (string unique with discriminator) - ranking (TBD whether float or integer. This represents my initial "best guess") list1 (list2, etc) - id (FK to abstract_list.id) - discriminator (FK to abstract_list.discriminator) - public_id (string or integer based on specific list. unique with discriminator) Solution 2: abstract_list - id (INT PK) - discriminator (string) - name (string unique with discriminator) - ranking (TBD whether float or integer. This represents my initial "best guess") - public_id (Application responsible to cast as string or integer. unique with discriminator) list1 (list2, etc. This class has no properties and only a method to cast the public ID as required. Seems like a waste...) - id (FK to abstract_list.id) I will then add another table to join each list to the user. user_list_ranking - abstract_list_id - user_id - ranking (TBD) To retrieve the list options, will query abstract_list and LEFT JOIN user_list_ranking and then sort on some mathematical formula acting on abstract_list.ranking and COALESCE(user_list_ranking.ranking, 0). To promote recent activity, maybe increment user_list_ranking.ranking every time the user selects a given option and also decrement all other options of the associated list. To prevent excessive windup, cap the the value to some max value (i.e. If list1 has a total of 10 records, cap it three times that value resulting in 30), and cap the minimum at zero. Uncharted territory here and am very open to other approaches. I am undecided whether I should just return an ordered array of the options, or also include either an order integer or some normalized value from 0 to 1. If there is a common way to do this, please let me know what it is so I may mimic it. If not, please provide any critique or recommended changes to my intended approach. Thanks
  17. Hi, Tried to log on with another machine yesterday and was unsuccessful. Didn't know I had an unused email linked to phpfreaks and while the new machine authentication screen didn't say an email was sent, expect/hope that was the case. The "other authentication" methods also seem to go no where. Pretty much one of the worst ux I've seen for this type of thing and recommend trying it out so you see yourself. Thanks
  18. NULL provides more context and also allows you to use other features as maxxd said, so my recommendation is to use NULL over an empty string.
  19. Thanks again for the help kicken, End up going almost exactly with your approach with a couple small changes. Instead of storing User in the listener class, stored LifecycleEventArgs so that I could get the before and after property values of User (needed to reverse an update to the API). Also, used postPersist instead of postFlush to remove the listener (never totally understood why this is even necessary, but all good). And thank you to requinix for your recommendation to perform that task which has the highest likelihood of failure first. <?php namespace App\EventListener; use Doctrine\Persistence\Event\LifecycleEventArgs; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use App\Service\HelpDeskClient; use App\Entity\AbstractUser; final class UserListner { private $helpDeskClient; private $dispatcher; private $initialEvent; public function __construct(HelpDeskClient $helpDeskClient, EventDispatcherInterface $dispatcher) { $this->helpDeskClient = $helpDeskClient; $this->dispatcher = $dispatcher; } public function prePersist(AbstractUser $entity, LifecycleEventArgs $event) { $this->sendHelpDeskRequest($event, 'persist'); } public function preUpdate(AbstractUser $entity, LifecycleEventArgs $event) { if($this->getHelpDeskChanges($event)) { // Only make a HTTP request if specific data is changed in user. $this->sendHelpDeskRequest($event, 'update'); } } public function preRemove (AbstractUser $entity, LifecycleEventArgs $event) { $this->sendHelpDeskRequest($event, 'remove'); } public function postPersist(AbstractUser $entity, LifecycleEventArgs $event) { $this->removeExceptionListener('persist'); } public function postUpdate(AbstractUser $entity, LifecycleEventArgs $event) { $this->removeExceptionListener('update'); } public function postRemove(AbstractUser $entity, LifecycleEventArgs $event) { $this->removeExceptionListener('remove'); } public function persistExceptionHandler(ExceptionEvent $event, $type, $dispatcher) { $this->helpDeskClient->removeUser($this->initialEvent->getEntity()); $this->removeExceptionListener('persist'); } public function updateExceptionHandler(ExceptionEvent $event, $type, $dispatcher) { $entity = $this->initialEvent->getEntity(); foreach($this->getHelpDeskChanges($this->initialEvent) as $name=>$values) { $entity->{'set'.$name}($values[0]); } $this->helpDeskClient->updateUser($entity); $this->removeExceptionListener('update'); } public function removeExceptionHandler(ExceptionEvent $event, $type, $dispatcher) { $this->helpDeskClient->addUser($this->initialEvent->getEntity()); $this->removeExceptionListener('remove'); } private function sendHelpDeskRequest(LifecycleEventArgs $initialEvent, string $action):self { $this->initialEvent = $initialEvent; $this->helpDeskClient->{$action.'User'}($this->initialEvent->getEntity()); $this->dispatcher->addListener(KernelEvents::EXCEPTION, [$this, $action.'ExceptionHandler']); return $this; } private function removeExceptionListener(string $action):self { $this->dispatcher->removeListener(KernelEvents::EXCEPTION, [$this, $action.'ExceptionHandler']); return $this; } private function getHelpDeskChanges(LifecycleEventArgs $initialEvent):array { return array_intersect_key($initialEvent->getEntityChangeSet(), array_flip($this->helpDeskClient->getUserProperties())); } }
  20. Sorry, my bad. That being said, listeners smell a little like a service but not exactly like one. Guess if they can be injected via Symphony's auto-wiring, they should be considered one, but don't know whether this is the case or not. Sounds like you somewhat agree. Don't envision working with multiple AbstractUsers at the same time, but then again I am often surprised when the impossible becomes the inevitable.
  21. Ah, of course! Thank you! As a matter of principle, would rather keep $this->helpDeskClient stateless and do it one of the following two ways if I am unable to pass both when adding the listener. Think the first approach is more "proper"? Off topic and sorry for asking all these questions, but what directory would a Symfony application typically locate the AbstractUserUpdater class? One thought is the same directory as HelpDeskClient (which I have in the App/Service namespace which maybe isn't correct?). Of maybe in the Entity namespace and just don't make it a Doctrine entity. EDIT. Actually, maybe it will not work as the postFlush() method can't be used. EDIT2. Or maybe it can and I just need to make make the function postFlush (AbstractUser $user, LifecycleEventArgs $event). EDIT3. No, that won't work either because I don't have the instance of AbstactUserUpdater, so maybe my second approach... public function prePersist(AbstractUser $user, LifecycleEventArgs $event) { $this->helpDeskClient->addUser($user); $this->dispatcher->addListener(KernelEvents::EXCEPTION, [new AbstractUserUpdater($user, $this), 'exceptionHandler']); } public function prePersist(AbstractUser $user, LifecycleEventArgs $event) { $this->helpDeskClient->addUser($user); $user->setHelpDeskClient($this); $this->dispatcher->addListener(KernelEvents::EXCEPTION, [$user, 'exceptionHandler']); }
  22. I now think I was completely off base for this part and should be thinking this way: Symfony events: kernel.request kernel.controller kernel.controller_arguments kernel.view kernel.response kernel.finish_request kernel.terminate kernel.exception No others, right? Third-party bundles Doctrine Events Etc...
  23. Thanks kicken, I would first like to try your first approach. I've always been confused when to use Doctrine events or Symfony events when used in a Symfony project. Obviously, Doctrine events should be used for a standalone (non-Symfony) project, but both Doctrine events and Symfony events are described in the Symfony documentation. I think I asked this before and you said that Doctrine events are only used for events related to the database and Symfony events are more encompassing. Do I have this right? Does this mean that I could always just use just Symfony events if I wanted (other I expect that Symfony events related to database operations use Doctrine events so maybe Doctrine events would be more performant). Makes sense, but somehow I would also need to get $user to be used by $this->helpDeskClient->rollback(). I tried $this->dispatcher->addListener(KernelEvents::EXCEPTION, [$this, $user, 'exceptionHandler']);, but no luck. I guess I could create a class which is injected with both UserListner and AbstractOwer, but seems like there should be a better way. Any thoughts? The postFlush is not being fired. Is its use appropriate? According to the Doctrine docs, postFlush - The postFlush event occurs at the end of a flush operation. this event is not a lifecycle callback. If not a lifecycle callback, what is it? App\EventListener\UserListner: tags: - name: 'doctrine.orm.entity_listener' event: 'prePersist' entity: 'App\Entity\AbstractUser' - name: 'doctrine.orm.entity_listener' event: 'postFlush' entity: 'App\Entity\AbstractUser'
  24. Not after getting your perspective Instead of validating the data for duplicates, I will make a POST request to the API, get the response, attempt to make an insert in the DB, call it good if the query goes through, but if on the rare chance it doesn't, need make another request to the API to reverse the action.
×
×
  • 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.