Making a Salt `onchanges` requisite dependent on what has changed - salt-stack

I want to execute a Salt state not always when changes happened in another state, but only for specific changes. This appears like I would have to make onchanges/onchanges_in dependent on the specific changes.
The respective bug report has been closed saying "this is totally resolved now that states have access to the running dict and the lowstate for a state run". However, I can find no documentation on that and hardly any explanation of what the "running dict" actually is.
So I guess the question could also be rephrased as "How do I access the 'running dict' in an onchanges requisite?", but I'm open to any solutions for the original problem. Thanks for your help!
Update: A comment asked for a specific example, so here is my use case: As most state modules, user.present may either update fields of an existing (user) object or create a new one. Then, I want to run a second state module if and only if a specific field has been changed and/or the object has just been created. In Ansible, for comparison, I would register a variable and access the module's result through it.
So, why would I want to do that?
Essentially, I want to create user accounts on Linux and have them be able to set their own password (when logged in via an SSH key). user.present supports empty_password for that purpose, but it doesn't play nicely with enforce_password. This means that after a password has been manually set, a repeated state run will clear that password again. One might even consider this a bug in Salt, but the interactions between the different user.present fields are convoluted and debatable.
My solution is to create the accounts first and run a module.run state executing shadow.del_password afterwards. This is realised through an onchanges_in requisite. However, password deletion should not be triggered for any change, but only when the user account is created, which is also the only case my user.present state touches the password at all. Otherwise, things like adding users to a group would clear their password. For that effect, I think I would have to look into the details of the user.present change.
Create user account for dummy:
user.present:
- name: dummy
- gid_from_name: True
- remove_groups: False
# TODO: This should be made more specific
- onchanges_in:
- module: Allow dummy to set a password
Allow dummy to set a password:
module.run:
- name: shadow.del_password
- m_name: dummy
# Make sure that this is not executed accidentally if no `onchanges_in` is present
- onchanges: []
- require:
- user: Create user account for dummy

I don't know about specific onchanges or the 'running dict', but, for your particular use case, you can use a condition to enable your password clearing state only when needed, such as:
Create user account for dummy:
user.present:
- name: dummy
- gid_from_name: True
- remove_groups: False
{% if salt['user.info']('dummy') == {} %}
# Only clear the password if the account didn't exist before
Allow dummy to set a password:
module.run:
- name: shadow.del_password
- m_name: dummy
- require:
- user: Create user account for dummy
{% endif %}

I think what you want to use in this case is module.wait, not module.run. module.wait by default will not do anything, unless asked by something else. Also, onchanges_in for some reason (I think this issue) doesn't play well with module.wait for me. I've tried watch_in and it did the job.
I've tried the following code and it seem to work just fine. It creates a user with an empty password and doesn't change anything if user is already there:
Create user account for dummy:
user.present:
- name: dummy
- gid_from_name: True
- remove_groups: False
# TODO: This should be made more specific
- watch_in:
- module: Allow dummy to set a password
Allow dummy to set a password:
module.wait:
- name: shadow.del_password
- m_name: dummy
- require:
- user: Create user account for dummy

Related

Request.auth.metadata in security rules?

I have a Firebase project where I'd like for users to be able to see when other users created their profiles. My initial hope was that I could use "user.metadata.creationTime" on the frontend to pass the date into the user's extra info document and verify that it is correct by having "request.resource.data.datecreated == request.auth.metadata.creationTime" as a Database Rule, but it looks like it is not possible according to the documentation.
Is there any way I can verify that the creation date is correct on the backend?
More info edit: Below is the code that is being triggered when a user creates a new account on my profile. The three values are displayed publicly. I'm creating a niche gear for sale page so being able to see when a user first created their account could be helpful when deciding if a seller is sketchy. I don't want someone to be able to make it seem like they have been around for longer than they have been.
db.collection('users').doc(user.uid).set({
username: "Username-156135",
bio: "Add a bio",
created: user.metadata.creationTime
});
Firestore rules:
match /users/{id} {
allow get;
allow create, update: if request.resource.data.username is string &&
request.resource.data.bio is string &&
request.resource.data.created == request.auth.metadata.creationTime;
}
user.metadata.creationTime, according to the API documentation is a string with no documented format. I suggest not using it. In fact, what you're trying to do seems impossible since that value isn't available in the API documentation for request.auth.
What I suggest you do instead is use a Firebase Auth onCreate trigger with Cloud Functions to automatically create that document with the current time as a proper timestamp. Then, in security rules, I wouldn't even give the user the ability to change that field, so you can be sure it was only ever set accurately by the trigger. You might be interested in this solution overall.

Two wordpress database with same users

I want to have the same WordPress users in two different databases
For example, if a user registers on SiteA, then he can login to SiteB. And reverse.
Also i want create same cookie for both after login.
mywebsite.com/ (SiteA_DB)
mywebsite.com/blog/ (SiteB_DB)
I've never done this before and maybe Wordpress has hooks to archive this, but I prefer using mysql for such a trick.
You could try ..
.. using 'federated storage' ( https://stackoverflow.com/a/24532395/10362812 )This is my favorite, because you don't even have to share a database or even the mysql serverThe downside is, that it doesn't work with db cache and uses an additional connection.
.. creating a 'view' ( https://stackoverflow.com/a/1890165/10362812 )This should be possible when using the database-name in the query itself and it would be the simplest solution if it works. Downside: The 2 tables have to share the same mysql-server and have to be assigned to the same user as far as I know.
-- **Backup your database before trying!** --
DROP TABLE `second_database`.`wp_users`;
DROP TABLE `second_database`.`wp_usermeta`;
CREATE VIEW `second_database`.`wp_users` AS SELECT * FROM `first_database`.`wp_users`;
CREATE VIEW `second_database`.`wp_usermeta` AS SELECT * FROM `first_database`.`wp_usermeta`;
This should work, according to: Creating view across different databases
.. creating a 'shadow copy' ( https://stackoverflow.com/a/1890166/10362812 )Works with caching and is a standalone tableDownsides as 2. solution + a bit of setup and I think it might be the worst option in performance
This were answers to this question: How do I create a table alias in MySQL
I merged them together for you and made them fit your use-case.
Please also notice, that solution 1 and 2 will replace your current user-tables auf "second_database" because you write directly into "first_database" when querying the fed. storage or the view. This can lead to problems with user-role plugins. You should take care of syncing the plugin-options too, if you should use one of them and in case it uses different tables or 'wp_options' values.
Let me know if this works, I have to do a similar task next week. While researching I found the linked answers.
EDIT: I was missing the point of "cookie-sharing" in my answer. Your example shows a blog on the same domain - you should be able to change the way wordpress sets its cookies to be domain-wide. What I did once for 2 different domains was, that I hooked into the backend (is_admin) and added a javascript which did a post-request to siteB, receiving a token which is stored but marked as 'invalid' on siteB. This token then was passed back to my plugin on siteA which checked if the user is logged_in and (in my case) have adminrights (current_user_can()) and if so, it was sending this token back to sideB which was marking this token as valid to login. (Make sure only sideA can tell sideB to make this token valid!) Once a user is seen with this token in a cookie on siteB, the user is logged-in automatically in the background. Also I made this bidirectional. I am sorry, that I can't share the code for you. I don't have access to it anymore.
Greetings, Eric!

FOS user bundle password validation

I'm trying to set up minimum character count limit for my users' password, using FOS User bundle, whether it is for registration or password reset
I've checked the documentation and searched on github issues / stackoverflow, but nothing is crystal clear to me. It seems that everyone has a different way to do this, and none seems to be matching my case.
First, I checked the documentation: https://symfony.com/doc/current/bundles/FOSUserBundle/overriding_validation.html
So I went to the validation.xml file and changed the plainpassword min size from 2 to 8:
<option name="min">8</option>
Yes, directly in the bundle. It was just to test. But it didn't changed anything
One of the way I found was to put an #Assert regex in the user entity, on the plainPassword field.
https://github.com/FriendsOfSymfony/FOSUserBundle/issues/986
Problem is: my passwords are encrypted, so I don't have any plain password field. Passwords get salted in the usersController upon registration, so this way fo doing is not applicable to my API, I believe.
So how would you achieve this in a quick and rather easy way?
Cheers!
As #IwanWijaya said you can follow the documentation
https://symfony.com/doc/3.3/bundles/override.html
src/Acme/UserBundle/Resources/config/validation.yml
FOS\UserBundle\Model\User:
properties:
plainPassword:
- NotBlank:
groups: [AcmeValidation]
- Length:
min: 6
minMessage: fos_user.password.short
groups: [AcmeValidation]

Link a person before that person has an account on Firebase

I plan to create an firebase tree solution to make possible to some operator link a person to some data before that person has an account.
So, when that person create its account, it will be possible to find that data. I was thinking about create some tree like this:
- Before_Signup_Link_User
- $user_email
- OperatorONE: true
- OperatorTWO: true
After signup and with its email informed on Firebase, the user would get the operator ID to find data on another path.
The problem is that Firebase does no let us put email as child. Do you have some ideia to do that.
Maybe you can use space char instead of dot char.
For Example:
- user#mail com
- OperatorONE: true
- OperatorTWO: true
a basic solution.. :)
From what I understand, Firebase doesn't allow some special characters (its indicated on their old docs, but I believe its still a valid rule on the new version)
A child node's key cannot be longer than 768 bytes, nor deeper than 32 levels. It can include any unicode characters except for . $ # [ ] / and ASCII control characters 0-31 and 127.
So if you want to use the email as child, you'll have to provide its proper unicode value

Add user role based on Profile2 Field Using Rules

What I am trying to achieve is:
1) I have a Profile2 field in the user registration form called: "Firm Type"
2) I need to assign the new user a Role based on the selection in this field.
I have tried the following:
Event: After saving a new account
Condition: Data Comparison: account:profile-additional-registration-info:field-profile-firm-type
Action: Add a user role
The above Rule works fine when I remove the condition. As soon as I add the condition the rule does not work.
Digging into this I found out that Rule gets executed after Account is saved and before Profile2 is saved.
I looked online to find these 2 links helpful:
https://www.drupal.org/node/1872384
https://www.drupal.org/node/2009878
1 suggestion was:
Event: After saving a new profile
Condition: Data Comparison: Profile2:field
Action: Heres where the problem is -- I cannot get to the account level because its on a profile event.
Could you please help me figure this out. Any help would be really appreaciated!
Thanks!
Here are the steps:
Rules Event: After adding a new profile After updating an existing profile
Rules Condition: Negate User Has Roles: Check all roles other than a Public Role Data Comparison: profile2:field
Rules Action: Set a Data Value: site:current-user:roles

Resources