-
Notifications
You must be signed in to change notification settings - Fork 844
[#10772] feat(authorization): refactor JcasbinAuthorizer with version-validated cache #10996
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
base: main
Are you sure you want to change the base?
Changes from all commits
6a44057
62ae012
d985bfb
7d30c8f
7a686f1
e74c005
7301353
3718d64
3deda80
63d331c
07c0ce0
7229cf6
4e2d2a3
1a6e163
9054927
113a5e4
540fec7
1566925
a42462a
6833ff3
fd98d97
c75338d
074baad
17cada9
166b3fd
c6e5b0a
31b6859
b834408
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.gravitino.server.authorization.jcasbin; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Cached snapshot of a group's role assignments. The {@code updatedAt} timestamp corresponds to the | ||
| * {@code group_meta.updated_at} column and is used as a version sentinel: if the DB value is newer, | ||
| * the cached role list is stale and must be reloaded. | ||
| */ | ||
| final class CachedGroupRoles { | ||
|
|
||
| private final long groupId; | ||
| private final long updatedAt; | ||
| private final List<Long> roleIds; | ||
|
|
||
| CachedGroupRoles(long groupId, long updatedAt, List<Long> roleIds) { | ||
| this.groupId = groupId; | ||
| this.updatedAt = updatedAt; | ||
| this.roleIds = roleIds; | ||
| } | ||
|
|
||
| long getGroupId() { | ||
| return groupId; | ||
| } | ||
|
|
||
| long getUpdatedAt() { | ||
| return updatedAt; | ||
| } | ||
|
|
||
| List<Long> getRoleIds() { | ||
| return roleIds; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.gravitino.server.authorization.jcasbin; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Cached snapshot of a user's direct role assignments. The {@code updatedAt} timestamp corresponds | ||
| * to the {@code user_meta.updated_at} column and is used as a version sentinel: if the DB value is | ||
| * newer, the cached role list is stale and must be reloaded. | ||
| */ | ||
| final class CachedUserRoles { | ||
|
|
||
| private final long userId; | ||
| private final long updatedAt; | ||
| private final List<Long> roleIds; | ||
|
|
||
| CachedUserRoles(long userId, long updatedAt, List<Long> roleIds) { | ||
| this.userId = userId; | ||
| this.updatedAt = updatedAt; | ||
| this.roleIds = roleIds; | ||
| } | ||
|
|
||
| long getUserId() { | ||
| return userId; | ||
| } | ||
|
|
||
| long getUpdatedAt() { | ||
| return updatedAt; | ||
| } | ||
|
|
||
| List<Long> getRoleIds() { | ||
| return roleIds; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you under the Apache License, Version 2.0 (the | ||
| * "License"); you may not use this file except in compliance | ||
| * with the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| package org.apache.gravitino.server.authorization.jcasbin; | ||
|
|
||
| import com.google.common.annotations.VisibleForTesting; | ||
| import org.apache.gravitino.MetadataObject; | ||
|
|
||
| /** Cache key factory for JCasbin authorization caches. */ | ||
| final class JcasbinAuthorizationCacheKeys { | ||
|
|
||
| /** Unit Separator for internal cache keys. */ | ||
| static final String SEPARATOR = "\u001F"; | ||
|
|
||
| private JcasbinAuthorizationCacheKeys() {} | ||
|
|
||
| /** | ||
| * Builds a path-based key for the metadata id cache. | ||
| * | ||
| * <p>Container objects end with the internal separator so prefix invalidation can remove both the | ||
| * container and entries under the same name path. Leaf objects include the type suffix to avoid | ||
| * collisions between objects that share the same name path. | ||
| */ | ||
| static String metadataObjectKey(String metalake, MetadataObject metadataObject) { | ||
| if (metadataObject.type() == MetadataObject.Type.METALAKE) { | ||
| return metalake + SEPARATOR; | ||
| } | ||
|
|
||
| StringBuilder sb = new StringBuilder(metalake); | ||
| sb.append(SEPARATOR); | ||
| sb.append(String.join(SEPARATOR, metadataObject.fullName().split("\\."))); | ||
| if (isMetadataContainer(metadataObject.type())) { | ||
| sb.append(SEPARATOR); | ||
| } else { | ||
| sb.append(SEPARATOR); | ||
| sb.append(metadataObject.type().name()); | ||
| } | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| static String userRoleKey(String metalake, String username) { | ||
| return "USER" + SEPARATOR + metalake + SEPARATOR + username; | ||
| } | ||
|
|
||
| static String groupRoleKey(String metalake, String groupname) { | ||
| return "GROUP" + SEPARATOR + metalake + SEPARATOR + groupname; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| static boolean isMetadataContainer(MetadataObject.Type type) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could u put this into MetadataObjectUtil? We should have a unified place to define this.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should have a better name. Because table can contain column. |
||
| return type == MetadataObject.Type.METALAKE | ||
| || type == MetadataObject.Type.CATALOG | ||
| || type == MetadataObject.Type.SCHEMA; | ||
| } | ||
| } | ||
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.
Should we use
metalake + SEPARATOR + USER_ROLE_REL SEPARATOR username?