/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed 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.constellation.database.impl.repository; import static org.constellation.database.api.jooq.Tables.CSTL_USER; import static org.constellation.database.api.jooq.Tables.USER_X_ROLE; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.constellation.database.api.UserWithRole; import org.constellation.database.api.jooq.Tables; import org.constellation.database.api.jooq.tables.pojos.CstlUser; import org.constellation.database.api.jooq.tables.records.CstlUserRecord; import org.constellation.database.api.jooq.tables.records.UserXRoleRecord; import org.constellation.database.api.repository.UserRepository; import org.jooq.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.google.common.base.Optional; @Component("cstlUserRepository") public class JooqUserRepository extends AbstractJooqRespository<CstlUserRecord, CstlUser> implements UserRepository { private final static Logger LOGGER = LoggerFactory.getLogger(MethodHandles .lookup().lookupClass()); public JooqUserRepository() { super(CstlUser.class, CSTL_USER); } @Override @Transactional(propagation = Propagation.MANDATORY) public CstlUser insert(CstlUser user) { CstlUserRecord record = dsl.newRecord(CSTL_USER); record.from(user); record.store(); return record.into(CstlUser.class); } @Override @Transactional(propagation = Propagation.MANDATORY) public CstlUser update(CstlUser user) { CstlUserRecord record = dsl.newRecord(CSTL_USER); record.from(user); dsl.executeUpdate(record); return record.into(CstlUser.class); } /** * This method remove current user role and add new role to user * @param userId * @param roleName */ @Override @Transactional(propagation = Propagation.MANDATORY) public void addUserToRole(Integer userId, String roleName) { //remove old role dsl.delete(USER_X_ROLE).where(USER_X_ROLE.USER_ID.eq(userId)).execute(); //set new role UserXRoleRecord record = dsl.newRecord(USER_X_ROLE); record.setUserId(userId); record.setRole(roleName); record.store(); } @Override @Transactional(propagation = Propagation.MANDATORY) public int delete(int userId) { int deleteRole = deleteRole(userId); LOGGER.debug("Delete " + deleteRole + " role references"); return dsl.delete(CSTL_USER).where(CSTL_USER.ID.eq(userId)).execute(); } @Override @Transactional(propagation = Propagation.MANDATORY) public int desactivate(int userId) { return dsl.update(Tables.CSTL_USER).set(CSTL_USER.ACTIVE, false) .where(CSTL_USER.ID.eq(userId)).execute(); } @Override @Transactional(propagation = Propagation.MANDATORY) public int activate(int userId) { return dsl.update(Tables.CSTL_USER).set(CSTL_USER.ACTIVE, true) .where(CSTL_USER.ID.eq(userId)).execute(); } private int deleteRole(int userId) { return dsl.delete(USER_X_ROLE).where(USER_X_ROLE.USER_ID.eq(userId)) .execute(); } @Override public boolean isLastAdmin(int userId) { Record1<Integer> where = dsl .selectCount() .from(CSTL_USER) .join(USER_X_ROLE) .onKey() .where(USER_X_ROLE.ROLE.eq("cstl-admin").and( CSTL_USER.ID.ne(userId))).fetchOne(); return where.value1() == 0; } @Override public Optional<CstlUser> findOne(String login) { if (login == null) return Optional.absent(); return Optional.fromNullable(dsl.select().from(CSTL_USER) .where(CSTL_USER.LOGIN.eq(login)).fetchOneInto(CstlUser.class)); } @Override public Optional<CstlUser> findById(Integer id) { if (id == null) return Optional.absent(); return Optional.fromNullable(dsl.select().from(CSTL_USER) .where(CSTL_USER.ID.eq(id)).fetchOneInto(CstlUser.class)); } @Override public Optional<CstlUser> findByEmail(String email) { if (email == null) return Optional.absent(); return Optional.fromNullable(dsl.select().from(CSTL_USER) .where(CSTL_USER.EMAIL.eq(email)).fetchOneInto(CstlUser.class)); } @Override public Optional<CstlUser> findByForgotPasswordUuid(String uuid) { if (uuid == null) return Optional.absent(); return Optional.fromNullable(dsl.select().from(CSTL_USER) .where(CSTL_USER.FORGOT_PASSWORD_UUID.eq(uuid)).fetchOneInto(CstlUser.class)); } @Override public List<String> getRoles(int userId) { return dsl.select().from(CSTL_USER) .where(USER_X_ROLE.USER_ID.eq(userId)).fetch(USER_X_ROLE.ROLE); } @Override public List<UserWithRole> findActivesWithRole() { Map<CstlUserRecord, Result<Record>> fetchGroups = dsl.select() .from(CSTL_USER).join(Tables.USER_X_ROLE).onKey().where(CSTL_USER.ACTIVE.isTrue()) .fetchGroups(CSTL_USER); return mapUserWithRole(fetchGroups); } /** * search pageable on cstl_user * @param search * @param size * @param page * @param sortFieldName fieldMapping[0] => table (ex: cstl_user), fieldMapping[1] => attribute (e.g name) * @param order * @return */ @Override public List<UserWithRole> search(String search, int size, int page, String sortFieldName, String order) { //prepare sort SortField<?> sortField = null; if(sortFieldName != null && !sortFieldName.isEmpty()){ String[] fieldMapping = sortFieldName.split("\\."); if(fieldMapping.length == 2){ String tableName = fieldMapping[0], attributeName = fieldMapping[1]; Field<?> field = null; if("user_x_role".equals(tableName)){ field = USER_X_ROLE.field(attributeName); } else if("cstl_user".equals(tableName)){ field = CSTL_USER.field(attributeName); } if(field != null){ sortField = field.sort(SortOrder.valueOf(order)); } else { LOGGER.warn("Sort on " + sortFieldName + " is not supported."); } } else { LOGGER.warn("Wrong sort value : " + sortFieldName + ", expected 'TABLE.ATTRIBUTE'"); } } Map<CstlUserRecord, Result<Record>> result = dsl.select().from(CSTL_USER) .leftOuterJoin(USER_X_ROLE).on(CSTL_USER.ID.eq(USER_X_ROLE.USER_ID)) .where(CSTL_USER.LOGIN.like(getLikePattern(search))) .orderBy(sortField) .limit(size) .offset((page - 1) * size) .fetchGroups(CSTL_USER); return mapUserWithRole(result); } @Override public long searchCount(String search) { return dsl.selectCount().from(CSTL_USER) .where(CSTL_USER.LOGIN.like(getLikePattern(search))) .fetchOne(0, Long.class); } @Override public Optional<UserWithRole> findOneWithRole(Integer id) { Map<CstlUserRecord, Result<Record>> fetchGroups = dsl.select() .from(CSTL_USER).leftOuterJoin(Tables.USER_X_ROLE).onKey() .where(CSTL_USER.ID.eq(id)).fetchGroups(CSTL_USER); if (fetchGroups.isEmpty()) { return Optional.absent(); } List<UserWithRole> users = mapUserWithRole(fetchGroups); return Optional.of(users.get(0)); } @Override public Optional<UserWithRole> findOneWithRole(String name) { Map<CstlUserRecord, Result<Record>> fetchGroups = dsl.select() .from(CSTL_USER).leftOuterJoin(Tables.USER_X_ROLE).onKey() .where(CSTL_USER.LOGIN.eq(name)).fetchGroups(CSTL_USER); if (fetchGroups.isEmpty()) { return Optional.absent(); } List<UserWithRole> users = mapUserWithRole(fetchGroups); return Optional.of(users.get(0)); } private List<UserWithRole> mapUserWithRole( Map<CstlUserRecord, Result<Record>> fetchGroups) { List<UserWithRole> ret = new ArrayList<>(); for (Map.Entry<CstlUserRecord, Result<Record>> e : fetchGroups .entrySet()) { UserWithRole userWithRole = e.getKey().into(UserWithRole.class); List<String> roles = e.getValue() .getValues(Tables.USER_X_ROLE.ROLE); userWithRole.setRoles(roles); ret.add(userWithRole); } return ret; } @Override public int countUser() { return dsl.selectCount().from(CSTL_USER).fetchOne(0, int.class); } @Override public boolean loginAvailable(String login) { return dsl.selectCount().from(CSTL_USER) .where(CSTL_USER.LOGIN.eq(login)).fetchOne().value1() == 0; } private String getLikePattern(String foo){ if(foo == null || foo.isEmpty()){ return "%"; } return "%" + foo + "%"; } }