-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement UserId #6759
Implement UserId #6759
Conversation
Please fix the conflicts. |
# Conflicts: # src/OrchardCore.Modules/OrchardCore.Users/Migrations.cs # src/OrchardCore.Modules/OrchardCore.Users/Views/UserButtons.cshtml
What does it breaks ? 🥰 |
Can't we create simply a SQL migration that would generate UID's for all the current existing user accounts instead of saving the actual NormalizedUserName in the UserId? Here is some SQL to generate UID's on the UserIndex, Document, ContentItemIndex table for existing users : DECLARE @count int
DECLARE @i int = 1
DECLARE @Migrate bit = 1
DECLARE @DocumentId int
DECLARE @NormalizedUserName nvarchar(255)
DECLARE @UserId nvarchar(26)
IF(@Migrate = 1)
BEGIN
SET @count = (SELECT COUNT(*) FROM UserIndex)
SET @i = 1
WHILE(@i <= @count)
BEGIN
WITH OrderedContentItem AS
(
SELECT DocumentId, NormalizedUserName,
ROW_NUMBER() OVER (ORDER BY Id) AS 'RowNumber'
FROM UserIndex
)
SELECT @DocumentId = DocumentId, @NormalizedUserName = NormalizedUserName FROM OrderedContentItem WHERE RowNumber = @i
SET @UserId = LEFT(LOWER(REPLACE(NEWID(), '-', '')), 26)
UPDATE UserIndex SET UserId = @UserId WHERE DocumentId = @DocumentId
-- We update Users in the Document table
UPDATE Document
SET Content = JSON_MODIFY(Content, '$.UserId', @UserId)
WHERE Id = @DocumentId
-- We add UserId on all ContentItems in Document table
UPDATE Document
SET Content = JSON_MODIFY(Content, '$.UserId', @UserId)
WHERE Type = 'OrchardCore.ContentManagement.ContentItem, OrchardCore.ContentManagement.Abstractions'
AND JSON_VALUE(Content, '$.Owner') = @NormalizedUserName
SELECT @i = @i + 1
END
END
-- Update ContentItemIndex table
UPDATE ContentItemIndex SET UserId = (SELECT JSON_VALUE(Content, '$.UserId') FROM Document WHERE Id = ContentItemIndex.DocumentId) @deanmarcussen Also in ContentItemIndex table we should also add a UserId column now. |
In OrchardCore.ContentManagement migrations.cs file. public int UpdateFrom5()
{
SchemaBuilder.AlterTable(nameof(ContentItemIndex), table => table
.AddColumn<string>("UserId", column => column.Nullable().WithLength(26))
);
return 6;
} |
So I did this to be migration free, because @sebastienros didn't want to run a migration. Otherwise when we do the OwnerId on ContentItems we will also have to run a migration against all the content items to move the owner over as well. Lot of risk of that failing due to timeouts on sites with large quantities of content items (or large quantities of users). Because of that I can't set the (we should probably fix that in code as well as currently it will just throw an exception depending on the database) If we did a migration we'd probably have to do it with YesSql, rather than SQL directly, to get support across all the databases (your sql script is great, but would it work on anything that isn't MS SQL?, i.e. postgres / mysql etc) |
I personally think it will require a SQL migration because a YesSQL migration could potentially cause a resquest timeout (maybe that's what meant @sebastienros). Also, I for exemple have a UserProfileIndex table which will require me to do a "custom migration" to a new UserId column . Of course, the SQL I wrote is a mock-up and works only in SQL Server but nothing prevents to compose the equivalent queries for other rdb's. Here, I just tried to show that it can be done without requiring YesSQL or adding a complex fixed code in OC. We're still in RC1, so we can still do breaking changes, I'd rather compose a SQL migration with some comments/procedures rather than trying to make something that migrates the data correctly only 90% with YesSQL... or that would require some changes to make it work without throwing a request timeout for large databases. Also using the email as a userid doesn't make it harder to guess like a uid is, I'd prefer generating a uid for all of them and be done with it at least.
The SQL Query covers that part and would be executed directly on the DB itself. Which means on prod the website would need to be closed for maintenance for the time the Query runs. And I think this will be required for all db types. @sebastienros On ne fait pas d'omelettes sans casser des œufs pour celle-ci 😉 An other option would be to create a small cross-plat app that could run the migration as a SQL Query with options to add the UserId on selected custom Index tables ; with database backup procedure and error logging. (More complex, but more efficient) |
Among every pending PRs, please focus on this one. |
Upgrade step, from the admin. |
Ok @Skrypt I made an Not as automatic as you might have liked. Still much todo, and merge conflicts to resolve, but some progress... |
Ok will pick up from there and make changes in a separate branch if I need to. |
# Conflicts: # src/OrchardCore.Modules/OrchardCore.Contents/Services/DefaultContentsAdminListFilter.cs # src/OrchardCore/OrchardCore.Setup.Core/SetupService.cs
@kevinchalet and @MichaelPetrinolis Here I am trying to do big risky things (without breaking anything) for good reasons... Would appreciate any input as to whether this will have any flow on effect on |
# Conflicts: # src/OrchardCore.Modules/OrchardCore.Contents/Services/DefaultContentsAdminListFilter.cs
Is the upgrade step completely transparent? |
It is, as there is no longer an upgrade step, but equally this pr is not finished / ready Still to be discussed. The blog recipe uses it for displaying the owner of a content item, and this is now being translated into a Guid. Should we have something like we do for tags, where Or should we be doing a lookup on the user table to get an owner name? (extra sql call) |
It is quite impossible to make the upgrade step completely transparent. Some people will have custom index providers that will need to be updated. If we talk about a fresh clean install then it will work. If we talk about existing websites with custom code it will surely require them to fix the code everywhere they make a relation between the User and the Owner name... We talk here about custom IndexingProviders, ContentEventHandlers and else. |
About |
@sebastienros I'm not sure what you are proposing. An author is quite different than a owner? |
I understand that, still one rock two birds. Then from what I see in the code, the author is "kept" across edits, which means the field is only changed if the users decides to do it, and we can even put names of people that don't exist. Audit trail with still record who (user id, TBD) changed the content. |
I think we need to define what is Author, Owner and what they should be used for. I see here in Github they use something similar but they also allow to link a user to a shortcode @Skrypt What would happen for example if we would change the Owner name now that we would have a UserId. Does that @skrypt-also shortcode will still render the proper UserId page? Same thing with the ContentItemIndex. We could keep the Owner name as a reference "in time" and also the "author" for that same matter. Though, the UserId should also be resolved in any case. So, if someone changes it's UserName, we don't require to update every content items he is related to. So basically 2 different use cases and which one we want to follow as a default? I think Audit Trail is an other topic of it's own unless we decide to have it enabled all the time by default. |
I think this is the way to go - we are only talking about the sample blog recipe. For the future I think One of the issues that bought this pr about was a It won't go into this pr, but it would follow shortly after, and I think it addresses the need for people to be able to define their own identification properties, for the variety of reasons / use cases, that they may have. So my proposal is keep it simple oob, and allow extension via a |
src/OrchardCore.Modules/OrchardCore.Settings/Deployment/SiteSettingsDeploymentSource.cs
Outdated
Show resolved
Hide resolved
src/OrchardCore/OrchardCore.Infrastructure/Security/AuthorizationHandlers/SuperUserHandler.cs
Outdated
Show resolved
Hide resolved
Updated after review with @sebastienros yesterday
Reviews welcome. @Skrypt you have done much with content permissions recently, so a test drive to ensure all continues correctly would be helpful. |
src/OrchardCore/OrchardCore.ContentManagement/Handlers/ContentsHandler.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@agriffard google for "trigger-happy" |
lol, it's fine really. I think the structure is there. If there's anything we will surely know it in the few next days. I really like the fact that we now use the Owner data as it should. |
Related to #5409
This is a start towards having a
UserId
throughout the OC ecosystem.It implements a
UserId
property forUsers
From the issue
Done in this pr
Done in this pr
Done in this pr
Done in this pr (see notes on where this maybe an issue)
In the context of permissions, this line from the
ContentTypeAuthorizationHandler
user.Identity.Name == content.Owner;
This should related to the
Name
Claim
property on claims.Nothing in this pr changes that.
The
UserId
(and previouslyDocumentId
) are mapped to theNameIdentifier
claim, ref: https://docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes.nameidentifierUser.Identity.Name should map to the
Name
claim, ref: https://docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes.nameidentifierSo for this pr nothing changes in relation to content ownership (next pr).
Done in this pr
The idea here is to introduce the
UserId
property on theIUser
as a guid / generated id, and later consider this in the context of content item ownership.I suspect we will want to consider storing both the
Owner
property as a historical value / friendly name for the ui, and anOwnerId
which would map to theClaim.NameIdentifier
->UserId