-
Notifications
You must be signed in to change notification settings - Fork 118
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
Prepare RepositoryMetadata role Updates for #1060 Compatibility #1061
Conversation
Motivation To ensure smooth compatibility with line#1060, the `PerRolePermissions` and `RepositoryMetadata` structure need an update to support changes. Modifications: - Enhanced the `PerRolePermissions` and `RepositoryMetadata` deserializers to accept both an array or permissions and a permission. - Added `REPO_ADMIN` `Permission`. - Removed `MetadataApiService.updateSpecificUserPermission` and `updateSpecificTokenPermission`. - They are not used in the UI and we don't even have test cases for that. - Will add those APIs later when we need it. Result: - The `PerRolePermissions` and `RepositoryMetadata` structures now support the upcoming changes in line#1060.
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.
👍 👍
import com.linecorp.centraldogma.internal.Jackson; | ||
import com.linecorp.centraldogma.server.QuotaConfig; | ||
|
||
final class RepositoryMetadataDeserializer extends StdDeserializer<RepositoryMetadata> { |
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.
I understood these custom deserializers will be removed once migration is complete
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.
That is correct. 👍 👍
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.
👍👍
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.
Understood the new changes
* Returns the {@link ProjectRoles} of the repository. | ||
*/ | ||
@JsonProperty("projects") | ||
public ProjectRoles projectRoles() { |
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.
I understood this property as: the default RepositoryRole
that will be assigned to project members that aren't explicitly set by users
and tokens
.
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.
the default RepositoryRole that will be assigned to project members
That's correct. 👍
that aren't explicitly set by users and tokens.
That is not correct. A RepositoryRole
can still be assigned to a user. The RepositoryRole
, which operates at a higher level, will be applied in such situation. https://github.com/line/centraldogma/pull/1060/files#diff-dc8a031ec8b91f16d76b42e152e9c3be8dd07b6f77bea922030074acc78ce78eR800-R823
throws IOException { | ||
final JsonNode jsonNode = p.readValueAsTree(); | ||
final String name = jsonNode.get("name").textValue(); | ||
final JsonNode perRolePermissionsNode = jsonNode.get("perRolePermissions"); |
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.
Note: I understood that if both perRolePermissions
and roles
is in the json node, then perRolePermissions
(the legacy format) has higher priority.
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.
I understood that if both perRolePermissions and roles is in the json node
They cannot be. Let me add an assertion logic. 😉
*/ | ||
WRITE, | ||
/** | ||
* Able to manage a repository. |
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.
Compared with the current permission scheme, I understood the difference is:
- the ability to set ADMIN for a repository
- repository settings can't change project admin roles.
This PR will be ready after #1069 is merged. |
.thenApply(CommitResult::revision) | ||
.exceptionally(cause -> { | ||
final Throwable peeled = Exceptions.peel(cause); | ||
if (peeled instanceof RedundantChangeException) { |
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.
I've realized that we don't need this logic anymore after introducing the transformer in #1069 because it will raise an IllegalArgumentException if there's no change.
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.
I'm not sure IllegalArgumentException
is a proper exception to understand the context.
final RepositoryMetadata repositoryMetadata = projectMetadata.repo(repoName); | ||
assert repositoryMetadata.name().equals(repoName); | ||
if (repositoryMetadata.perRolePermissions().equals(perRolePermissions)) { | ||
throw new IllegalArgumentException( |
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.
What do you think of raising RedundantChangeException
instead?
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.
That's a good suggestion! How about the following approach:
- Introduce
UserNotFoundException
- This exception would be used exclusively on the server side, similar to
TokenNotFoundException
.
- This exception would be used exclusively on the server side, similar to
- Raise
UserNotFoundException
andTokenNotFoundException
- These exceptions would be triggered when attempting to update an entity that doesn't exist.
- Raise
RedundantChangeException
- This exception would be raised when an update is attempted with the same content as the existing one.
- The
RedundantChangeException
would be swallowed, and the system would simply return the head revision. In other words, users wouldn’t encounter this exception."
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.
Updated, PTAL. 🙇
server/src/main/java/com/linecorp/centraldogma/server/metadata/ProjectRoles.java
Show resolved
Hide resolved
.thenApply(CommitResult::revision) | ||
.exceptionally(cause -> { | ||
final Throwable peeled = Exceptions.peel(cause); | ||
if (peeled instanceof RedundantChangeException) { |
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.
I'm not sure IllegalArgumentException
is a proper exception to understand the context.
final String commitSummary = | ||
"Update the role permission of the '" + repoName + "' in the project '" + projectName + '\''; | ||
return metadataRepo.push(projectName, Project.REPO_DOGMA, author, commitSummary, change); | ||
final ContentTransformer<JsonNode> transformer = new ContentTransformer<>( | ||
METADATA_JSON, EntryType.JSON, node -> { |
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.
Optional) I could see some code similar to this in other places. How about creating RepositoryMetadataTransformer
and duplicating them?
private static class RepositoryMetadataTransformer extends ContentTransformer {
RepositoryMetadataTransformer(Function<RepositoryMetadata, RepositoryMetadata>) {
...
}
}
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.
That's a good suggestion. 👍
RepositoryMetadataTransformer
, ProjectMetadataTransformer
and TokensTransformer
are added. 😉
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.
Thanks! 👍
for (Entry<String, Token> entry : tokens.appIds().entrySet()) { | ||
if (!entry.getKey().equals(appId)) { | ||
appIdsBuilder.put(entry); | ||
} else { | ||
appIdsBuilder.put(appId, newToken); | ||
} | ||
} |
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.
Side note: It seems useful if we have an ImmutableMap
utility that helps to update or remove.
class ImmutableMapUtil {
Map<K, V> remove(Map<K, V> old, K key) {
// create a new map and remove `key`.
...
}
Map<K, V> add(Map<K, V> old, K key, V value) { ... }
}
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.
That looks useful. 👍 Let me try that later. 😉
Motivation
To ensure smooth compatibility with #1060, the
RepositoryMetadata
structure needs an update to support changes.AS-IS:
TO-BE:
Modifications:
RepositoryMetadata
deserializers to accept both legacy and new formats.RepositoryRole
.Permission
.MetadataApiService.updateSpecificUserPermission
andupdateSpecificTokenPermission
.Result:
RepositoryMetadata
structure now supports the upcoming changes in Introduce Role-Based Authentication for Repository Management #1060.