User entity migrated to jdbi3

This commit is contained in:
sureshms 2021-10-21 18:11:05 -07:00
parent ca187378c3
commit a919367a2b
11 changed files with 194 additions and 144 deletions

View File

@ -85,7 +85,7 @@ public class CatalogApplication extends Application<CatalogApplicationConfig> {
// Register Authorizer // Register Authorizer
registerAuthorizer(catalogConfig, environment, jdbi); registerAuthorizer(catalogConfig, environment, jdbi3);
// Registering config api // Registering config api
environment.jersey().register(new ConfigResource(catalogConfig)); environment.jersey().register(new ConfigResource(catalogConfig));
@ -104,7 +104,7 @@ public class CatalogApplication extends Application<CatalogApplicationConfig> {
environment.jersey().register(new JsonProcessingExceptionMapper(true)); environment.jersey().register(new JsonProcessingExceptionMapper(true));
environment.jersey().register(new EarlyEofExceptionMapper()); environment.jersey().register(new EarlyEofExceptionMapper());
environment.jersey().register(JsonMappingExceptionMapper.class); environment.jersey().register(JsonMappingExceptionMapper.class);
environment.healthChecks().register("UserDatabaseCheck", new CatalogHealthCheck(catalogConfig, jdbi)); environment.healthChecks().register("UserDatabaseCheck", new CatalogHealthCheck(catalogConfig, jdbi3));
registerResources(catalogConfig, environment, jdbi); registerResources(catalogConfig, environment, jdbi);
registerResources(catalogConfig, environment, jdbi3); registerResources(catalogConfig, environment, jdbi3);
@ -132,7 +132,7 @@ public class CatalogApplication extends Application<CatalogApplicationConfig> {
super.initialize(bootstrap); super.initialize(bootstrap);
} }
private void registerAuthorizer(CatalogApplicationConfig catalogConfig, Environment environment, DBI jdbi) private void registerAuthorizer(CatalogApplicationConfig catalogConfig, Environment environment, Jdbi jdbi)
throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException,
InstantiationException { InstantiationException {
AuthorizerConfiguration authorizerConf = catalogConfig.getAuthorizerConfiguration(); AuthorizerConfiguration authorizerConf = catalogConfig.getAuthorizerConfiguration();

View File

@ -17,29 +17,29 @@
package org.openmetadata.catalog; package org.openmetadata.catalog;
import com.codahale.metrics.health.HealthCheck; import com.codahale.metrics.health.HealthCheck;
import org.openmetadata.catalog.entity.teams.User; import org.jdbi.v3.core.Jdbi;
import org.openmetadata.catalog.jdbi3.UserRepository; import org.openmetadata.catalog.jdbi3.UserRepository3;
import org.openmetadata.catalog.jdbi3.UserRepositoryHelper;
import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil;
import org.openmetadata.catalog.util.ResultList;
import org.skife.jdbi.v2.DBI;
import java.io.IOException; import java.io.IOException;
import static org.openmetadata.catalog.resources.teams.UserResource.FIELD_LIST; import static org.openmetadata.catalog.resources.teams.UserResource.FIELD_LIST;
public class CatalogHealthCheck extends HealthCheck { public class CatalogHealthCheck extends HealthCheck {
private final UserRepository userRepository; private final UserRepositoryHelper userRepositoryHelper;
private final EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, "profile"); private final EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, "profile");
public CatalogHealthCheck(CatalogApplicationConfig config, DBI jdbi) { public CatalogHealthCheck(CatalogApplicationConfig config, Jdbi jdbi) {
super(); super();
this.userRepository = jdbi.onDemand(UserRepository.class); UserRepository3 repo = jdbi.onDemand(UserRepository3.class);
this.userRepositoryHelper = new UserRepositoryHelper(repo);
} }
@Override @Override
protected Result check() throws Exception { protected Result check() throws Exception {
try { try {
ResultList<User> users = userRepository.listAfter(fields, 1, ""); userRepositoryHelper.listAfter(fields, 1, "");
return Result.healthy(); return Result.healthy();
} catch (IOException e) { } catch (IOException e) {
return Result.unhealthy(e.getMessage()); return Result.unhealthy(e.getMessage());

View File

@ -26,4 +26,23 @@ public interface UserDAO3 extends EntityDAO<User> {
@Override @Override
@SqlQuery("SELECT count(*) FROM <table>") @SqlQuery("SELECT count(*) FROM <table>")
int listCount(@Define("table") String table); int listCount(@Define("table") String table);
@SqlQuery(
"SELECT json FROM (" +
"SELECT name, json FROM user_entity WHERE " +
"name < :before " + // Pagination by user name
"ORDER BY name DESC " + // Pagination ordering by user name
"LIMIT :limit" +
") last_rows_subquery ORDER BY name")
List<String> listBefore(@org.skife.jdbi.v2.sqlobject.Bind("limit") int limit, @org.skife.jdbi.v2.sqlobject.Bind("before") String before);
@SqlQuery("SELECT json FROM user_entity WHERE " +
"name > :after " + // Pagination by user name
"ORDER BY name " + // Pagination ordering by user name
"LIMIT :limit")
List<String> listAfter(@org.skife.jdbi.v2.sqlobject.Bind("limit") int limit, @org.skife.jdbi.v2.sqlobject.Bind("after") String after);
@SqlQuery("SELECT count(*) FROM user_entity")
int listCount();
} }

View File

@ -0,0 +1,60 @@
/*
* 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.openmetadata.catalog.jdbi3;
import org.jdbi.v3.sqlobject.CreateSqlObject;
public interface UserRepository3 {
@CreateSqlObject
UserDAO3 userDAO();
@CreateSqlObject
EntityRelationshipDAO3 relationshipDAO();
@CreateSqlObject
TeamDAO3 teamDAO();
@CreateSqlObject
TableDAO3 tableDAO();
@CreateSqlObject
DatabaseDAO3 databaseDAO();
@CreateSqlObject
MetricsDAO3 metricsDAO();
@CreateSqlObject
DashboardDAO3 dashboardDAO();
@CreateSqlObject
ReportDAO3 reportDAO();
@CreateSqlObject
TopicDAO3 topicDAO();
@CreateSqlObject
ChartDAO3 chartDAO();
@CreateSqlObject
TaskDAO3 taskDAO();
@CreateSqlObject
PipelineDAO3 pipelineDAO();
@CreateSqlObject
ModelDAO3 modelDAO();
}

View File

@ -25,14 +25,13 @@ import org.openmetadata.catalog.resources.teams.UserResource.UserList;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
import org.openmetadata.catalog.type.TagLabel; import org.openmetadata.catalog.type.TagLabel;
import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityInterface;
import org.openmetadata.catalog.util.EntityUpdater; import org.openmetadata.catalog.util.EntityUpdater3;
import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil;
import org.openmetadata.catalog.util.EntityUtil.Fields; import org.openmetadata.catalog.util.EntityUtil.Fields;
import org.openmetadata.catalog.util.JsonUtils; import org.openmetadata.catalog.util.JsonUtils;
import org.openmetadata.catalog.util.RestUtil; import org.openmetadata.catalog.util.RestUtil;
import org.openmetadata.catalog.util.RestUtil.PutResponse; import org.openmetadata.catalog.util.RestUtil.PutResponse;
import org.openmetadata.catalog.util.ResultList; import org.openmetadata.catalog.util.ResultList;
import org.skife.jdbi.v2.sqlobject.CreateSqlObject;
import org.skife.jdbi.v2.sqlobject.Transaction; import org.skife.jdbi.v2.sqlobject.Transaction;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -55,11 +54,15 @@ import static org.openmetadata.catalog.jdbi3.Relationship.CONTAINS;
import static org.openmetadata.catalog.jdbi3.Relationship.FOLLOWS; import static org.openmetadata.catalog.jdbi3.Relationship.FOLLOWS;
import static org.openmetadata.catalog.jdbi3.Relationship.OWNS; import static org.openmetadata.catalog.jdbi3.Relationship.OWNS;
public abstract class UserRepository { public class UserRepositoryHelper implements EntityRepository<User> {
public static final Logger LOG = LoggerFactory.getLogger(UserRepository.class); public static final Logger LOG = LoggerFactory.getLogger(UserRepositoryHelper.class);
static final Fields USER_PATCH_FIELDS = new Fields(UserResource.FIELD_LIST, "profile,teams"); static final Fields USER_PATCH_FIELDS = new Fields(UserResource.FIELD_LIST, "profile,teams");
static final Fields USER_UPDATE_FIELDS = new Fields(UserResource.FIELD_LIST, "profile,teams"); static final Fields USER_UPDATE_FIELDS = new Fields(UserResource.FIELD_LIST, "profile,teams");
public UserRepositoryHelper(UserRepository3 repo3) { this.repo3 = repo3; }
private final UserRepository3 repo3;
public static List<EntityReference> toEntityReference(List<Team> teams) { public static List<EntityReference> toEntityReference(List<Team> teams) {
if (teams == null) { if (teams == null) {
return null; return null;
@ -71,87 +74,22 @@ public abstract class UserRepository {
return refList; return refList;
} }
@CreateSqlObject @Override
abstract UserDAO userDAO(); public ResultList<User> getResultList(List<User> entities, String beforeCursor, String afterCursor,
int total) throws GeneralSecurityException, UnsupportedEncodingException {
@CreateSqlObject return new UserList(entities, beforeCursor, afterCursor, total);
abstract EntityRelationshipDAO relationshipDAO();
@CreateSqlObject
abstract TeamDAO teamDAO();
@CreateSqlObject
abstract TableDAO tableDAO();
@CreateSqlObject
abstract DatabaseDAO databaseDAO();
@CreateSqlObject
abstract MetricsDAO metricsDAO();
@CreateSqlObject
abstract DashboardDAO dashboardDAO();
@CreateSqlObject
abstract ReportDAO reportDAO();
@CreateSqlObject
abstract TopicDAO topicDAO();
@CreateSqlObject
abstract ChartDAO chartDAO();
@CreateSqlObject
abstract TaskDAO taskDAO();
@CreateSqlObject
abstract PipelineDAO pipelineDAO();
@CreateSqlObject
abstract ModelDAO modelDAO();
EntityRepository<User> entityRepository = new EntityRepository<User>() {
@Override
public List<String> listAfter(String fqnPrefix, int limitParam, String after) {
return UserRepository.this.userDAO().listAfter(limitParam, after);
}
@Override
public List<String> listBefore(String fqnPrefix, int limitParam, String before) {
return UserRepository.this.userDAO().listBefore(limitParam, before);
}
@Override
public int listCount(String fqnPrefix) {
return UserRepository.this.userDAO().listCount();
}
@Override
public String getFullyQualifiedName(User entity) {
// User does not have a FullyQualifiedName but needs a valid field to paginate
return entity.getName();
}
@Override
public User setFields(User entity, Fields fields) throws IOException, ParseException {
return UserRepository.this.setFields(entity, fields);
}
@Override
public ResultList<User> getResultList(List<User> entities, String beforeCursor, String afterCursor,
int total) throws GeneralSecurityException, UnsupportedEncodingException {
return new UserList(entities, beforeCursor, afterCursor, total);
}
};
@Transaction
public ResultList<User> listAfter(Fields fields, int limitParam, String after) throws IOException, GeneralSecurityException, ParseException {
return EntityUtil.listAfter(entityRepository, User.class, fields, null, limitParam, after);
} }
@Transaction @Transaction
public ResultList<User> listBefore(Fields fields, int limitParam, String before) throws IOException, GeneralSecurityException, ParseException { public ResultList<User> listAfter(Fields fields, int limitParam, String after) throws IOException,
return EntityUtil.listBefore(entityRepository, User.class, fields, null, limitParam, before); GeneralSecurityException, ParseException {
return EntityUtil.listAfter(this, User.class, fields, null, limitParam, after);
}
@Transaction
public ResultList<User> listBefore(Fields fields, int limitParam, String before) throws IOException,
GeneralSecurityException, ParseException {
return EntityUtil.listBefore(this, User.class, fields, null, limitParam, before);
} }
@Transaction @Transaction
@ -167,13 +105,13 @@ public abstract class UserRepository {
@Transaction @Transaction
public User getByName(String name, Fields fields) throws IOException { public User getByName(String name, Fields fields) throws IOException {
User user = EntityUtil.validate(name, userDAO().findByName(name), User.class); User user = repo3.userDAO().findEntityByName(name);
return setFields(user, fields); return setFields(user, fields);
} }
@Transaction @Transaction
public User getByEmail(String email, Fields fields) throws IOException { public User getByEmail(String email, Fields fields) throws IOException {
User user = EntityUtil.validate(email, userDAO().findByEmail(email), User.class); User user = EntityUtil.validate(email, repo3.userDAO().findByEmail(email), User.class);
return setFields(user, fields); return setFields(user, fields);
} }
@ -189,15 +127,15 @@ public abstract class UserRepository {
User user = markUserAsDeactivated(id); User user = markUserAsDeactivated(id);
// Remove relationship membership to teams // Remove relationship membership to teams
relationshipDAO().deleteTo(user.getId().toString(), CONTAINS.ordinal(), "team"); repo3.relationshipDAO().deleteTo(user.getId().toString(), CONTAINS.ordinal(), "team");
// Remove follows relationship to entities // Remove follows relationship to entities
relationshipDAO().deleteFrom(id, FOLLOWS.ordinal()); repo3.relationshipDAO().deleteFrom(id, FOLLOWS.ordinal());
} }
@Transaction @Transaction
public RestUtil.PutResponse<User> createOrUpdate(User updated) throws IOException { public RestUtil.PutResponse<User> createOrUpdate(User updated) throws IOException {
User stored = JsonUtils.readValue(userDAO().findByName(updated.getName()), User.class); User stored = JsonUtils.readValue(repo3.userDAO().findJsonByFqn(updated.getName()), User.class);
// TODO why are we doing this? // TODO why are we doing this?
List<UUID> teamIds = new ArrayList<>(); List<UUID> teamIds = new ArrayList<>();
@ -243,12 +181,33 @@ public abstract class UserRepository {
// Patch can't make changes to following fields. Ignore the changes // Patch can't make changes to following fields. Ignore the changes
updated.withName(original.getName()).withId(original.getId()); updated.withName(original.getName()).withId(original.getId());
validateRelationships(updated, teamIds); validateRelationships(updated, teamIds);
UserRepository.UserUpdater userUpdater = new UserRepository.UserUpdater(original, updated, true); UserRepositoryHelper.UserUpdater userUpdater = new UserRepositoryHelper.UserUpdater(original, updated, true);
userUpdater.updateAll(); userUpdater.updateAll();
userUpdater.store(); userUpdater.store();
} }
private User setFields(User user, Fields fields) throws IOException { @Override
public List<String> listAfter(String fqnPrefix, int limitParam, String after) {
return null;
}
@Override
public List<String> listBefore(String fqnPrefix, int limitParam, String before) {
return null;
}
@Override
public int listCount(String fqnPrefix) {
return 0;
}
@Override
public String getFullyQualifiedName(User entity) {
return null;
}
@Override
public User setFields(User user, Fields fields) throws IOException {
user.setProfile(fields.contains("profile") ? user.getProfile() : null); user.setProfile(fields.contains("profile") ? user.getProfile() : null);
user.setTeams(fields.contains("teams") ? getTeams(user) : null); user.setTeams(fields.contains("teams") ? getTeams(user) : null);
user.setOwns(fields.contains("owns") ? getOwns(user) : null); user.setOwns(fields.contains("owns") ? getOwns(user) : null);
@ -258,26 +217,26 @@ public abstract class UserRepository {
private List<EntityReference> getOwns(User user) throws IOException { private List<EntityReference> getOwns(User user) throws IOException {
// Compile entities owned by the user // Compile entities owned by the user
List<EntityReference> ownedEntities = relationshipDAO().findTo(user.getId().toString(), OWNS.ordinal()); List<EntityReference> ownedEntities = repo3.relationshipDAO().findTo(user.getId().toString(), OWNS.ordinal());
// Compile entities owned by the team the user belongs to // Compile entities owned by the team the user belongs to
List<EntityReference> teams = user.getTeams() == null ? getTeams(user) : user.getTeams(); List<EntityReference> teams = user.getTeams() == null ? getTeams(user) : user.getTeams();
for (EntityReference team : teams) { for (EntityReference team : teams) {
ownedEntities.addAll(relationshipDAO().findTo(team.getId().toString(), OWNS.ordinal())); ownedEntities.addAll(repo3.relationshipDAO().findTo(team.getId().toString(), OWNS.ordinal()));
} }
// Populate details in entity reference // Populate details in entity reference
return EntityUtil.getEntityReference(ownedEntities, tableDAO(), databaseDAO(), metricsDAO(), dashboardDAO(), return EntityUtil.getEntityReference(ownedEntities, repo3.tableDAO(), repo3.databaseDAO(), repo3.metricsDAO(), repo3.dashboardDAO(),
reportDAO(), topicDAO(), chartDAO(), taskDAO(), modelDAO(), pipelineDAO()); repo3.reportDAO(), repo3.topicDAO(), repo3.chartDAO(), repo3.taskDAO(), repo3.modelDAO(), repo3.pipelineDAO());
} }
private List<EntityReference> getFollows(User user) throws IOException { private List<EntityReference> getFollows(User user) throws IOException {
return EntityUtil.getEntityReference(relationshipDAO().findTo(user.getId().toString(), FOLLOWS.ordinal()), return EntityUtil.getEntityReference(repo3.relationshipDAO().findTo(user.getId().toString(), FOLLOWS.ordinal()),
tableDAO(), databaseDAO(), metricsDAO(), dashboardDAO(), reportDAO(), topicDAO(), chartDAO(), taskDAO(), repo3.tableDAO(), repo3.databaseDAO(), repo3.metricsDAO(), repo3.dashboardDAO(), repo3.reportDAO(),
modelDAO(), pipelineDAO()); repo3.topicDAO(), repo3.chartDAO(), repo3.taskDAO(), repo3.modelDAO(), repo3.pipelineDAO());
} }
private User validateUser(String userId) throws IOException { private User validateUser(String userId) throws IOException {
return EntityUtil.validate(userId, userDAO().findById(userId), User.class); return repo3.userDAO().findEntityById(userId);
} }
private User createInternal(User user) throws IOException { private User createInternal(User user) throws IOException {
@ -302,9 +261,9 @@ public abstract class UserRepository {
user.withTeams(null).withHref(null); user.withTeams(null).withHref(null);
if (update) { if (update) {
userDAO().update(user.getId().toString(), JsonUtils.pojoToJson(user)); repo3.userDAO().update(user.getId().toString(), JsonUtils.pojoToJson(user));
} else { } else {
userDAO().insert(JsonUtils.pojoToJson(user)); repo3.userDAO().insert(JsonUtils.pojoToJson(user));
} }
// Restore the relationships // Restore the relationships
@ -317,19 +276,18 @@ public abstract class UserRepository {
} }
List<EntityReference> validatedTeams = new ArrayList<>(); List<EntityReference> validatedTeams = new ArrayList<>();
for (UUID teamId : teamIds) { for (UUID teamId : teamIds) {
validatedTeams.add(EntityUtil.getEntityReference( validatedTeams.add(EntityUtil.getEntityReference(repo3.teamDAO().findEntityById(teamId.toString())));
EntityUtil.validate(teamId.toString(), teamDAO().findById(teamId.toString()), Team.class)));
} }
return validatedTeams; return validatedTeams;
} }
/* Add all the teams that user belongs to to User entity */ /* Add all the teams that user belongs to to User entity */
private List<EntityReference> getTeams(User user) throws IOException { private List<EntityReference> getTeams(User user) throws IOException {
List<String> teamIds = relationshipDAO().findFrom(user.getId().toString(), CONTAINS.ordinal(), "team"); List<String> teamIds = repo3.relationshipDAO().findFrom(user.getId().toString(), CONTAINS.ordinal(), "team");
List<Team> teams = new ArrayList<>(); List<Team> teams = new ArrayList<>();
for (String teamId : teamIds) { for (String teamId : teamIds) {
LOG.debug("Adding team {}", teamId); LOG.debug("Adding team {}", teamId);
String json = teamDAO().findById(teamId); String json = repo3.teamDAO().findJsonById(teamId);
Team team = JsonUtils.readValue(json, Team.class); Team team = JsonUtils.readValue(json, Team.class);
if (team != null) { if (team != null) {
teams.add(team); teams.add(team);
@ -341,7 +299,7 @@ public abstract class UserRepository {
private void assignTeams(User user, List<EntityReference> teams) { private void assignTeams(User user, List<EntityReference> teams) {
// Query - add team to the user // Query - add team to the user
for (EntityReference team : teams) { for (EntityReference team : teams) {
relationshipDAO().insert(team.getId().toString(), user.getId().toString(), repo3.relationshipDAO().insert(team.getId().toString(), user.getId().toString(),
"team", "user", CONTAINS.ordinal()); "team", "user", CONTAINS.ordinal());
} }
} }
@ -353,9 +311,9 @@ public abstract class UserRepository {
return user; return user;
} }
user.setDeactivated(true); user.setDeactivated(true);
user.setName("deactivated." +user.getName()); user.setName("deactivated." + user.getName());
user.setDisplayName("Deactivated " +user.getDisplayName()); user.setDisplayName("Deactivated " + user.getDisplayName());
userDAO().update(id, JsonUtils.pojoToJson(user)); repo3.userDAO().update(id, JsonUtils.pojoToJson(user));
return user; return user;
} }
@ -403,13 +361,13 @@ public abstract class UserRepository {
/** /**
* Handles entity updated from PUT and POST operation. * Handles entity updated from PUT and POST operation.
*/ */
public class UserUpdater extends EntityUpdater { public class UserUpdater extends EntityUpdater3 {
final User orig; final User orig;
final User updated; final User updated;
public UserUpdater(User orig, User updated, boolean patchOperation) { public UserUpdater(User orig, User updated, boolean patchOperation) {
super(new UserRepository.UserEntityInterface(orig), new UserRepository.UserEntityInterface(updated), super(new UserRepositoryHelper.UserEntityInterface(orig), new UserRepositoryHelper.UserEntityInterface(updated),
patchOperation, relationshipDAO(), null); patchOperation, repo3.relationshipDAO(), null);
this.orig = orig; this.orig = orig;
this.updated = updated; this.updated = updated;
} }
@ -425,11 +383,12 @@ public abstract class UserRepository {
public void updateTeams() { public void updateTeams() {
// Remove teams from original and add teams from updated // Remove teams from original and add teams from updated
relationshipDAO().deleteTo(orig.getId().toString(), CONTAINS.ordinal(), "team"); repo3.relationshipDAO().deleteTo(orig.getId().toString(), CONTAINS.ordinal(), "team");
if (!updated.getTeams().isEmpty()) { if (!updated.getTeams().isEmpty()) {
assignTeams(updated, updated.getTeams()); assignTeams(updated, updated.getTeams());
} }
} }
public void store() throws IOException { public void store() throws IOException {
updated.setVersion(getNewVersion(orig.getVersion())); updated.setVersion(getNewVersion(orig.getVersion()));
storeUser(updated, true); storeUser(updated, true);

View File

@ -51,6 +51,8 @@ import org.openmetadata.catalog.jdbi3.TeamRepository3;
import org.openmetadata.catalog.jdbi3.TeamRepositoryHelper; import org.openmetadata.catalog.jdbi3.TeamRepositoryHelper;
import org.openmetadata.catalog.jdbi3.TopicRepository3; import org.openmetadata.catalog.jdbi3.TopicRepository3;
import org.openmetadata.catalog.jdbi3.TopicRepositoryHelper; import org.openmetadata.catalog.jdbi3.TopicRepositoryHelper;
import org.openmetadata.catalog.jdbi3.UserRepository3;
import org.openmetadata.catalog.jdbi3.UserRepositoryHelper;
import org.openmetadata.catalog.resources.bots.BotsResource; import org.openmetadata.catalog.resources.bots.BotsResource;
import org.openmetadata.catalog.resources.charts.ChartResource; import org.openmetadata.catalog.resources.charts.ChartResource;
import org.openmetadata.catalog.resources.dashboards.DashboardResource; import org.openmetadata.catalog.resources.dashboards.DashboardResource;
@ -66,6 +68,7 @@ import org.openmetadata.catalog.resources.services.messaging.MessagingServiceRes
import org.openmetadata.catalog.resources.services.pipeline.PipelineServiceResource; import org.openmetadata.catalog.resources.services.pipeline.PipelineServiceResource;
import org.openmetadata.catalog.resources.tasks.TaskResource; import org.openmetadata.catalog.resources.tasks.TaskResource;
import org.openmetadata.catalog.resources.teams.TeamResource; import org.openmetadata.catalog.resources.teams.TeamResource;
import org.openmetadata.catalog.resources.teams.UserResource;
import org.openmetadata.catalog.resources.topics.TopicResource; import org.openmetadata.catalog.resources.topics.TopicResource;
import org.openmetadata.catalog.type.CollectionDescriptor; import org.openmetadata.catalog.type.CollectionDescriptor;
import org.openmetadata.catalog.type.CollectionInfo; import org.openmetadata.catalog.type.CollectionInfo;
@ -319,6 +322,13 @@ public final class CollectionRegistry {
environment.jersey().register(teamResource); environment.jersey().register(teamResource);
LOG.info("Registering {}", teamResource); LOG.info("Registering {}", teamResource);
final UserRepository3 userRepository3 = jdbi.onDemand(UserRepository3.class);
UserRepositoryHelper userRepositoryHelper = new UserRepositoryHelper(userRepository3);
UserResource userResource = new UserResource(userRepositoryHelper,
authorizer);
environment.jersey().register(userResource);
LOG.info("Registering {}", userResource);
LOG.info("Initialized jdbi3"); LOG.info("Initialized jdbi3");
} }

View File

@ -29,7 +29,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.openmetadata.catalog.api.teams.CreateUser; import org.openmetadata.catalog.api.teams.CreateUser;
import org.openmetadata.catalog.entity.teams.User; import org.openmetadata.catalog.entity.teams.User;
import org.openmetadata.catalog.jdbi3.UserRepository; import org.openmetadata.catalog.jdbi3.UserRepositoryHelper;
import org.openmetadata.catalog.resources.Collection; import org.openmetadata.catalog.resources.Collection;
import org.openmetadata.catalog.security.CatalogAuthorizer; import org.openmetadata.catalog.security.CatalogAuthorizer;
import org.openmetadata.catalog.security.SecurityUtil; import org.openmetadata.catalog.security.SecurityUtil;
@ -76,11 +76,11 @@ import java.util.UUID;
@Api(value = "User collection", tags = "User collection") @Api(value = "User collection", tags = "User collection")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Collection(name = "users", repositoryClass = "org.openmetadata.catalog.jdbi3.UserRepository") //@Collection(name = "users", repositoryClass = "org.openmetadata.catalog.jdbi3.UserRepositoryHelper")
public class UserResource { public class UserResource {
public static final Logger LOG = LoggerFactory.getLogger(UserResource.class); public static final Logger LOG = LoggerFactory.getLogger(UserResource.class);
public static final String USER_COLLECTION_PATH = "v1/users/"; public static final String USER_COLLECTION_PATH = "v1/users/";
private final UserRepository dao; private final UserRepositoryHelper dao;
private final CatalogAuthorizer authorizer; private final CatalogAuthorizer authorizer;
public static void addHref(UriInfo uriInfo, EntityReference user) { public static void addHref(UriInfo uriInfo, EntityReference user) {
@ -96,8 +96,8 @@ public class UserResource {
} }
@Inject @Inject
public UserResource(UserRepository dao, CatalogAuthorizer authorizer) { public UserResource(UserRepositoryHelper dao, CatalogAuthorizer authorizer) {
Objects.requireNonNull(dao, "UserRepository must not be null"); Objects.requireNonNull(dao, "UserRepositoryHelper must not be null");
this.dao = dao; this.dao = dao;
this.authorizer = authorizer; this.authorizer = authorizer;
} }

View File

@ -16,15 +16,15 @@
package org.openmetadata.catalog.security; package org.openmetadata.catalog.security;
import org.jdbi.v3.core.Jdbi;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
import org.skife.jdbi.v2.DBI;
public interface CatalogAuthorizer { public interface CatalogAuthorizer {
/** /**
* Initialize the authorizer * Initialize the authorizer
*/ */
void init(AuthorizerConfiguration config, DBI jdbi); void init(AuthorizerConfiguration config, Jdbi jdbi);
/** /**
* Check if the authenticated user has given permission on the target entity * Check if the authenticated user has given permission on the target entity

View File

@ -17,14 +17,15 @@
package org.openmetadata.catalog.security; package org.openmetadata.catalog.security;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jdbi.v3.core.Jdbi;
import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.Entity;
import org.openmetadata.catalog.entity.teams.User; import org.openmetadata.catalog.entity.teams.User;
import org.openmetadata.catalog.exception.DuplicateEntityException; import org.openmetadata.catalog.exception.DuplicateEntityException;
import org.openmetadata.catalog.exception.EntityNotFoundException; import org.openmetadata.catalog.exception.EntityNotFoundException;
import org.openmetadata.catalog.jdbi3.UserRepository; import org.openmetadata.catalog.jdbi3.UserRepository3;
import org.openmetadata.catalog.jdbi3.UserRepositoryHelper;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.EntityUtil;
import org.skife.jdbi.v2.DBI;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -43,18 +44,19 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
private Set<String> botUsers; private Set<String> botUsers;
private String principalDomain; private String principalDomain;
private UserRepository userRepository; private UserRepositoryHelper userRepositoryHelper;
private final String fieldsParam = "teams"; private final String fieldsParam = "teams";
@Override @Override
public void init(AuthorizerConfiguration config, DBI dbi) { public void init(AuthorizerConfiguration config, Jdbi dbi) {
LOG.debug("Initializing DefaultCatalogAuthorizer with config {}", config); LOG.debug("Initializing DefaultCatalogAuthorizer with config {}", config);
this.adminUsers = new HashSet<>(config.getAdminPrincipals()); this.adminUsers = new HashSet<>(config.getAdminPrincipals());
this.botUsers = new HashSet<>(config.getBotPrincipals()); this.botUsers = new HashSet<>(config.getBotPrincipals());
this.principalDomain = config.getPrincipalDomain(); this.principalDomain = config.getPrincipalDomain();
LOG.debug("Admin users: {}", adminUsers); LOG.debug("Admin users: {}", adminUsers);
this.userRepository = dbi.onDemand(UserRepository.class); UserRepository3 repo = dbi.onDemand(UserRepository3.class);
this.userRepositoryHelper = new UserRepositoryHelper(repo);
mayBeAddAdminUsers(); mayBeAddAdminUsers();
mayBeAddBotUsers(); mayBeAddBotUsers();
} }
@ -65,7 +67,7 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
adminUsers.stream() adminUsers.stream()
.filter(name -> { .filter(name -> {
try { try {
User user = userRepository.getByName(name, fields); User user = userRepositoryHelper.getByName(name, fields);
if (user != null) { if (user != null) {
LOG.debug("Entry for user '{}' already exists", name); LOG.debug("Entry for user '{}' already exists", name);
return false; return false;
@ -84,7 +86,7 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
botUsers.stream() botUsers.stream()
.filter(name -> { .filter(name -> {
try { try {
User user = userRepository.getByName(name, fields); User user = userRepositoryHelper.getByName(name, fields);
if (user != null) { if (user != null) {
LOG.debug("Entry for user '{}' already exists", name); LOG.debug("Entry for user '{}' already exists", name);
return false; return false;
@ -108,7 +110,7 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
String userName = SecurityUtil.getUserName(ctx); String userName = SecurityUtil.getUserName(ctx);
EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, fieldsParam); EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, fieldsParam);
try { try {
User user = userRepository.getByName(userName, fields); User user = userRepositoryHelper.getByName(userName, fields);
if (owner.getType().equals(Entity.TEAM)) { if (owner.getType().equals(Entity.TEAM)) {
for (EntityReference team: user.getTeams()) { for (EntityReference team: user.getTeams()) {
if (team.getName().equals(owner.getName())) { if (team.getName().equals(owner.getName())) {
@ -130,7 +132,7 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
String userName = SecurityUtil.getUserName(ctx); String userName = SecurityUtil.getUserName(ctx);
EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, fieldsParam); EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, fieldsParam);
try { try {
User user = userRepository.getByName(userName, fields); User user = userRepositoryHelper.getByName(userName, fields);
if (user.getIsAdmin() == null) { if (user.getIsAdmin() == null) {
return false; return false;
} }
@ -146,7 +148,7 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
String userName = SecurityUtil.getUserName(ctx); String userName = SecurityUtil.getUserName(ctx);
EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, fieldsParam); EntityUtil.Fields fields = new EntityUtil.Fields(FIELD_LIST, fieldsParam);
try { try {
User user = userRepository.getByName(userName, fields); User user = userRepositoryHelper.getByName(userName, fields);
if (user.getIsBot() == null) { if (user.getIsBot() == null) {
return false; return false;
} }
@ -171,7 +173,7 @@ public class DefaultCatalogAuthorizer implements CatalogAuthorizer {
.withUpdatedAt(new Date()); .withUpdatedAt(new Date());
try { try {
User addedUser = userRepository.create(user, null); User addedUser = userRepositoryHelper.create(user, null);
LOG.debug("Added bot user entry: {}", addedUser); LOG.debug("Added bot user entry: {}", addedUser);
} catch (DuplicateEntityException | IOException exception) { } catch (DuplicateEntityException | IOException exception) {
// In HA setup the other server may have already added the user. // In HA setup the other server may have already added the user.

View File

@ -16,8 +16,8 @@
package org.openmetadata.catalog.security; package org.openmetadata.catalog.security;
import org.jdbi.v3.core.Jdbi;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
import org.skife.jdbi.v2.DBI;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -26,7 +26,7 @@ public class NoopAuthorizer implements CatalogAuthorizer {
@Override @Override
public void init(AuthorizerConfiguration config, DBI jdbi) { public void init(AuthorizerConfiguration config, Jdbi jdbi) {
} }
@Override @Override

View File

@ -26,7 +26,7 @@ import org.openmetadata.catalog.entity.data.Table;
import org.openmetadata.catalog.entity.teams.Team; import org.openmetadata.catalog.entity.teams.Team;
import org.openmetadata.catalog.entity.teams.User; import org.openmetadata.catalog.entity.teams.User;
import org.openmetadata.catalog.exception.CatalogExceptionMessage; import org.openmetadata.catalog.exception.CatalogExceptionMessage;
import org.openmetadata.catalog.jdbi3.UserRepository; import org.openmetadata.catalog.jdbi3.UserRepositoryHelper;
import org.openmetadata.catalog.resources.databases.TableResourceTest; import org.openmetadata.catalog.resources.databases.TableResourceTest;
import org.openmetadata.catalog.resources.teams.UserResource.UserList; import org.openmetadata.catalog.resources.teams.UserResource.UserList;
import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.EntityReference;
@ -507,7 +507,7 @@ public class UserResourceTest extends CatalogApplicationTest {
// Update the user attributes // Update the user attributes
before.setDisplayName(displayName); before.setDisplayName(displayName);
before.setTeams(UserRepository.toEntityReference(teams)); before.setTeams(UserRepositoryHelper.toEntityReference(teams));
before.setProfile(profile); before.setProfile(profile);
before.setTimezone(timezone); before.setTimezone(timezone);
before.setIsBot(isBot); before.setIsBot(isBot);