Signup flow
This commit is contained in:
parent
f71bd9a4e0
commit
bea5f53f46
|
|
@ -47,6 +47,7 @@ public class ClientUserRepository implements ServerOAuth2AuthorizedClientReposit
|
|||
private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME;
|
||||
UserService userService;
|
||||
OrganizationService organizationService;
|
||||
|
||||
public ClientUserRepository(UserService userService, OrganizationService organizationService) {
|
||||
this.userService = userService;
|
||||
this.organizationService = organizationService;
|
||||
|
|
@ -92,20 +93,8 @@ public class ClientUserRepository implements ServerOAuth2AuthorizedClientReposit
|
|||
newUser.setState(UserState.ACTIVATED);
|
||||
newUser.setIsEnabled(true);
|
||||
|
||||
/** TODO
|
||||
* Organization here is being hardcoded. This is a stop gap measure
|
||||
* A flow needs to be added to connect a User to a Organization. Once
|
||||
* that is done, during the login, the organization should be picked up
|
||||
* and a user should be hence created.
|
||||
*/
|
||||
|
||||
return organizationService.findById("5d3e90a2dfec7c00047a81ea")
|
||||
.map(organization -> {
|
||||
newUser.setOrganization(organization);
|
||||
return newUser;
|
||||
})
|
||||
.then(userService.findByEmail(user.getEmail()))
|
||||
.switchIfEmpty(userService.save(newUser));
|
||||
return userService.findByEmail(user.getEmail())
|
||||
.switchIfEmpty(userService.save(newUser)); //In case the user doesnt exist, save the user.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ public interface Url {
|
|||
String SETTING_URL = BASE_URL + VERSION + "/settings";
|
||||
String RESOURCE_URL = BASE_URL + VERSION + "/resources";
|
||||
String ACTION_URL = BASE_URL + VERSION + "/actions";
|
||||
String USER_URL = BASE_URL + VERSION + "/users";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.appsmith.server.controllers;
|
||||
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.services.UserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
|
@ -13,8 +16,16 @@ import java.security.Principal;
|
|||
@RequestMapping("")
|
||||
public class IndexController {
|
||||
|
||||
private final UserService service;
|
||||
|
||||
@Autowired
|
||||
public IndexController(UserService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Mono<String> index(Mono<Principal> principal) {
|
||||
Mono<User> userMono = service.getCurrentUser();
|
||||
return principal
|
||||
.map(Principal::getName)
|
||||
.map(name -> String.format("Hello %s", name));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package com.appsmith.server.controllers;
|
||||
|
||||
import com.appsmith.server.constants.Url;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.services.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(Url.USER_URL)
|
||||
public class UserController extends BaseController<UserService, User, String> {
|
||||
|
||||
@Autowired
|
||||
public UserController(UserService service) {
|
||||
super(service);
|
||||
}
|
||||
}
|
||||
|
|
@ -33,9 +33,9 @@ public class User extends BaseDomain implements UserDetails {
|
|||
|
||||
private UserState state;
|
||||
|
||||
private Boolean isEnabled;
|
||||
private Boolean isEnabled = true;
|
||||
|
||||
private Organization organization;
|
||||
private String organizationId;
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public enum AppsmithError {
|
|||
|
||||
NO_RESOURCE_FOUND(404, 1000, "Unable to find {0} with id {1}"),
|
||||
INVALID_PARAMETER(400, 4000, "Invalid parameter {0} provided in the input"),
|
||||
PLUGIN_NOT_INSTALLED(400, 4001, "Plugin not installed for organization {0}"),
|
||||
PLUGIN_NOT_INSTALLED(400, 4001, "Plugin {0} not installed"),
|
||||
PLUGIN_ID_NOT_GIVEN(400, 4002, "Missing plugin id. Please input correct plugin id"),
|
||||
RESOURCE_ID_NOT_GIVEN(400, 4003, "Missing resource id. Please input correct resource id"),
|
||||
INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request");
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class GlobalExceptionHandler {
|
|||
*
|
||||
* @param e AppsmithException that will be caught by the function
|
||||
* @param exchange ServerWebExchange contract in order to extract the response and set the http status code
|
||||
* @return Mono<ResponseDto < ErrorDTO>>
|
||||
* @return Mono<ResponseDto < ErrorDTO>>
|
||||
*/
|
||||
@ExceptionHandler
|
||||
@ResponseBody
|
||||
|
|
@ -40,7 +40,7 @@ public class GlobalExceptionHandler {
|
|||
*
|
||||
* @param e Exception that will be caught by the function
|
||||
* @param exchange ServerWebExchange contract in order to extract the response and set the http status code
|
||||
* @return Mono<ResponseDto < ErrorDTO>>
|
||||
* @return Mono<ResponseDto < ErrorDTO>>
|
||||
*/
|
||||
@ExceptionHandler
|
||||
@ResponseBody
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.appsmith.server.helpers;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class BeanCopyUtils {
|
||||
|
||||
private static String[] getNullPropertyNames(Object source) {
|
||||
final BeanWrapper src = new BeanWrapperImpl(source);
|
||||
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
|
||||
|
||||
Set<String> emptyNames = new HashSet<String>();
|
||||
for (java.beans.PropertyDescriptor pd : pds) {
|
||||
Object srcValue = src.getPropertyValue(pd.getName());
|
||||
if (srcValue == null) {
|
||||
emptyNames.add(pd.getName());
|
||||
}
|
||||
}
|
||||
String[] result = new String[emptyNames.size()];
|
||||
return emptyNames.toArray(result);
|
||||
}
|
||||
|
||||
//Use Spring BeanUtils to copy and ignore null
|
||||
public static void copyNewFieldValuesIntoOldObject(Object src, Object target) {
|
||||
BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
|
|||
|
||||
@Override
|
||||
public Mono<T> getById(ID id) {
|
||||
if(id == null) {
|
||||
if (id == null) {
|
||||
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID));
|
||||
}
|
||||
|
||||
|
|
@ -98,12 +98,12 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
|
|||
*/
|
||||
protected Mono<T> validateObject(T obj) {
|
||||
return Mono.just(obj)
|
||||
.map(o -> validator.validate(o))
|
||||
.flatMap(constraint -> {
|
||||
if(constraint.isEmpty()) {
|
||||
return Mono.just(obj);
|
||||
}
|
||||
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, constraint.stream().findFirst().get().getPropertyPath()));
|
||||
});
|
||||
.map(o -> validator.validate(o))
|
||||
.flatMap(constraint -> {
|
||||
if (constraint.isEmpty()) {
|
||||
return Mono.just(obj);
|
||||
}
|
||||
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, constraint.stream().findFirst().get().getPropertyPath()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +1,17 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.server.configurations.ClientUserRepository;
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.OrganizationPlugin;
|
||||
import com.appsmith.server.domains.Plugin;
|
||||
import com.appsmith.server.domains.PluginType;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.dtos.OrganizationPluginStatus;
|
||||
import com.appsmith.server.dtos.PluginOrgDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.repositories.PluginRepository;
|
||||
import com.appsmith.server.repositories.UserRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
|
|
@ -30,13 +28,9 @@ import java.util.List;
|
|||
public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, String> implements PluginService {
|
||||
|
||||
private final PluginRepository pluginRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final ApplicationContext applicationContext;
|
||||
private final ClientUserRepository clientUserRepository;
|
||||
private final OrganizationService organizationService;
|
||||
|
||||
@Value("${organization.id}")
|
||||
private String organizationId;
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public PluginServiceImpl(Scheduler scheduler,
|
||||
|
|
@ -44,16 +38,13 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
|
|||
MongoConverter mongoConverter,
|
||||
ReactiveMongoTemplate reactiveMongoTemplate,
|
||||
PluginRepository repository,
|
||||
UserRepository userRepository,
|
||||
ApplicationContext applicationContext,
|
||||
ClientUserRepository clientUserRepository,
|
||||
OrganizationService organizationService) {
|
||||
OrganizationService organizationService, UserService userService) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
|
||||
this.userRepository = userRepository;
|
||||
this.applicationContext = applicationContext;
|
||||
pluginRepository = repository;
|
||||
this.clientUserRepository = clientUserRepository;
|
||||
this.organizationService = organizationService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
public PluginExecutor getPluginExecutor(PluginType pluginType, String className) {
|
||||
|
|
@ -90,29 +81,17 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
|
|||
|
||||
@Override
|
||||
public Mono<Organization> uninstallPlugin(PluginOrgDTO pluginDTO) {
|
||||
/*TODO
|
||||
* Organization & user association is being mocked here by forcefully
|
||||
* only using a hardcoded organization. This needs to be replaced by
|
||||
* a user-organization association flow. The Organization needs to be picked
|
||||
* up from a user object. This is being used in install/uninstall
|
||||
* plugin from a organization flow. Instead, the current user should be read
|
||||
* using the following :
|
||||
* ReactiveSecurityContextHolder.getContext()
|
||||
* .map(SecurityContext::getAuthentication)
|
||||
* .map(Authentication::getPrincipal);
|
||||
* Once the user has been pulled using this, organization should already
|
||||
* be stored as part of user and this organization should be used to store
|
||||
* the installed plugin or to delete plugin during uninstallation.
|
||||
*/
|
||||
if (pluginDTO.getPluginId() == null) {
|
||||
return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN));
|
||||
}
|
||||
|
||||
//Find the organization using id and plugin id -> This is to find if the organization has the plugin installed
|
||||
Mono<Organization> organizationMono = organizationService.findByIdAndPluginsPluginId(organizationId, pluginDTO.getPluginId());
|
||||
Mono<User> userMono = userService.getCurrentUser();
|
||||
Mono<Organization> organizationMono = userMono.flatMap(user ->
|
||||
organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), pluginDTO.getPluginId()));
|
||||
|
||||
return organizationMono
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, organizationId)))
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, pluginDTO.getPluginId())))
|
||||
//In case the plugin is not found for the organization, the organizationMono would not emit and the rest of the flow would stop
|
||||
//i.e. the rest of the code flow would only happen when there is a plugin found for the organization that can
|
||||
//be uninstalled.
|
||||
|
|
@ -126,40 +105,33 @@ public class PluginServiceImpl extends BaseService<PluginRepository, Plugin, Str
|
|||
}
|
||||
|
||||
private Mono<Organization> storeOrganizationPlugin(PluginOrgDTO pluginDTO, OrganizationPluginStatus status) {
|
||||
/*TODO
|
||||
* Organization & user association is being mocked here by forcefully
|
||||
* only using a hardcoded organization. This needs to be replaced by
|
||||
* a user-organization association flow. The Organization needs to be picked
|
||||
* up from a user object. This is being used in install/uninstall
|
||||
* plugin from a organization flow. Instead, the current user should be read
|
||||
* using the following :
|
||||
* ReactiveSecurityContextHolder.getContext()
|
||||
* .map(SecurityContext::getAuthentication)
|
||||
* .map(Authentication::getPrincipal);
|
||||
* Once the user has been pulled using this, organization should already
|
||||
* be stored as part of user and this organization should be used to store
|
||||
* the installed plugin or to delete plugin during uninstalling.
|
||||
*/
|
||||
|
||||
//Find the organization using id and plugin id -> This is to find if the organization already has the plugin installed
|
||||
Mono<Organization> organizationMono = organizationService.findByIdAndPluginsPluginId(organizationId, pluginDTO.getPluginId());
|
||||
Mono<User> userMono = userService.getCurrentUser();
|
||||
Mono<Organization> organizationMono = userMono.flatMap(user ->
|
||||
organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), pluginDTO.getPluginId()));
|
||||
|
||||
|
||||
//If plugin is already present for the organization, just return the organization, else install and return organization
|
||||
return organizationMono
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
//If the plugin is not found in the organization, its not already installed. Install now.
|
||||
return organizationService.findById(organizationId).map(organization -> {
|
||||
List<OrganizationPlugin> organizationPluginList = organization.getPlugins();
|
||||
if (organizationPluginList == null) {
|
||||
organizationPluginList = new ArrayList<OrganizationPlugin>();
|
||||
}
|
||||
log.debug("Installing plugin {} for organization {}", pluginDTO.getPluginId(), organization.getName());
|
||||
OrganizationPlugin organizationPlugin = new OrganizationPlugin();
|
||||
organizationPlugin.setPluginId(pluginDTO.getPluginId());
|
||||
organizationPlugin.setStatus(status);
|
||||
organizationPluginList.add(organizationPlugin);
|
||||
organization.setPlugins(organizationPluginList);
|
||||
return organization;
|
||||
}).flatMap(organizationService::save);
|
||||
//If the plugin is not found in the organization, its not installed already. Install now.
|
||||
return userMono
|
||||
.flatMap(user -> organizationService.findById(user.getOrganizationId()))
|
||||
.map(organization -> {
|
||||
List<OrganizationPlugin> organizationPluginList = organization.getPlugins();
|
||||
if (organizationPluginList == null) {
|
||||
organizationPluginList = new ArrayList<OrganizationPlugin>();
|
||||
}
|
||||
log.debug("Installing plugin {} for organization {}", pluginDTO.getPluginId(), organization.getName());
|
||||
OrganizationPlugin organizationPlugin = new OrganizationPlugin();
|
||||
organizationPlugin.setPluginId(pluginDTO.getPluginId());
|
||||
organizationPlugin.setStatus(status);
|
||||
organizationPluginList.add(organizationPlugin);
|
||||
organization.setPlugins(organizationPluginList);
|
||||
return organization;
|
||||
})
|
||||
.flatMap(organizationService::save);
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ package com.appsmith.server.services;
|
|||
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.Resource;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.repositories.ResourceRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -21,19 +21,16 @@ import javax.validation.constraints.NotNull;
|
|||
@Service
|
||||
public class ResourceServiceImpl extends BaseService<ResourceRepository, Resource, String> implements ResourceService {
|
||||
|
||||
@Value("${organization.id}")
|
||||
private String organizationId;
|
||||
|
||||
private final ResourceRepository repository;
|
||||
private final OrganizationService organizationService;
|
||||
private final PluginService pluginService;
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, OrganizationService organizationService, PluginService pluginService) {
|
||||
public ResourceServiceImpl(Scheduler scheduler, Validator validator, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, ResourceRepository repository, OrganizationService organizationService, PluginService pluginService, UserService userService) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
|
||||
this.repository = repository;
|
||||
this.organizationService = organizationService;
|
||||
this.pluginService = pluginService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -44,17 +41,19 @@ public class ResourceServiceImpl extends BaseService<ResourceRepository, Resourc
|
|||
return Mono.error(new AppsmithException(AppsmithError.PLUGIN_ID_NOT_GIVEN));
|
||||
}
|
||||
|
||||
Mono<Organization> organizationMono = organizationService.findByIdAndPluginsPluginId(organizationId, resource.getPluginId());
|
||||
Mono<User> userMono = userService.getCurrentUser();
|
||||
|
||||
Mono<Organization> organizationMono = userMono.flatMap(user -> organizationService.findByIdAndPluginsPluginId(user.getOrganizationId(), resource.getPluginId()));
|
||||
|
||||
//Add organization id to the resource.
|
||||
Mono<Resource> updatedResourceMono = Mono.just(resource)
|
||||
.map(updatedResource -> {
|
||||
updatedResource.setOrganizationId(organizationId);
|
||||
return updatedResource;
|
||||
Mono<Resource> updatedResourceMono = organizationMono
|
||||
.map(organization -> {
|
||||
resource.setOrganizationId(organization.getId());
|
||||
return resource;
|
||||
});
|
||||
|
||||
return organizationMono
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, organizationId)))
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.PLUGIN_NOT_INSTALLED, resource.getPluginId())))
|
||||
.then(updatedResourceMono)
|
||||
.flatMap(repository::save);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,4 +10,6 @@ public interface UserService extends CrudService<User, String> {
|
|||
Mono<User> findByEmail(String email);
|
||||
|
||||
Mono<User> save(User newUser);
|
||||
|
||||
Mono<User> getCurrentUser();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +1,43 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.helpers.BeanCopyUtils;
|
||||
import com.appsmith.server.repositories.UserRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
|
||||
import javax.validation.Validator;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class UserServiceImpl extends BaseService<UserRepository, User, String> implements UserService, UserDetailsService {
|
||||
|
||||
private UserRepository repository;
|
||||
private final OrganizationService organizationService;
|
||||
|
||||
@Autowired
|
||||
public UserServiceImpl(Scheduler scheduler,
|
||||
Validator validator,
|
||||
MongoConverter mongoConverter,
|
||||
ReactiveMongoTemplate reactiveMongoTemplate,
|
||||
UserRepository repository) {
|
||||
UserRepository repository, OrganizationService organizationService) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository);
|
||||
this.repository = repository;
|
||||
this.organizationService = organizationService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -46,4 +59,55 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return repository.findByName(username).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<User> getCurrentUser() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.map(Authentication::getPrincipal)
|
||||
.flatMap(principal -> {
|
||||
String email;
|
||||
if (principal instanceof org.springframework.security.core.userdetails.User) {
|
||||
org.springframework.security.core.userdetails.User user = (org.springframework.security.core.userdetails.User) principal;
|
||||
//Assumption that the user has inputted an email as username during user creation and not english passport name
|
||||
email = user.getUsername();
|
||||
} else {
|
||||
DefaultOidcUser defaultOidcUser = (DefaultOidcUser) principal;
|
||||
email = defaultOidcUser.getEmail();
|
||||
}
|
||||
return repository.findByEmail(email);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<User> update(String id, User userUpdate) {
|
||||
Mono<User> userFromRepository = repository.findById(id);
|
||||
|
||||
return Mono.just(userUpdate)
|
||||
.flatMap(this::validateUpdate)
|
||||
//Once the new update has been validated, update the user with the new fields.
|
||||
.then(userFromRepository)
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, id)))
|
||||
.map(existingUser -> {
|
||||
BeanCopyUtils.copyNewFieldValuesIntoOldObject(userUpdate, existingUser);
|
||||
return existingUser;
|
||||
})
|
||||
.flatMap(repository::save);
|
||||
}
|
||||
|
||||
//Validation for user update. Right now it only validates the organization id. Other checks can be added
|
||||
//here in the future.
|
||||
private Mono<User> validateUpdate(User updateUser) {
|
||||
if (updateUser.getOrganizationId() == null) {
|
||||
//No organization present implies the update to the user is not to the organization id. No checks currently
|
||||
//for this scenario. Return the user successfully.
|
||||
return Mono.just(updateUser);
|
||||
}
|
||||
return organizationService.findById(updateUser.getOrganizationId())
|
||||
//If the organization is not found in the repository, throw an error
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, updateUser.getOrganizationId())))
|
||||
.then(Mono.just(updateUser));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.domains.UserState;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class UserServiceTest {
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
@Autowired
|
||||
OrganizationService organizationService;
|
||||
|
||||
Mono<User> userMono;
|
||||
Mono<Organization> organizationMono;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
//User init
|
||||
User user = new User();
|
||||
user.setName("user test");
|
||||
user.setEmail("usertest@usertest.com");
|
||||
user.setState(UserState.ACTIVATED);
|
||||
//Store the user in case its not present in the database.
|
||||
userMono = userService.findByEmail("usertest@usertest.com").switchIfEmpty(Mono.defer(() -> userService.save(user)));
|
||||
|
||||
//Organization init
|
||||
Organization organization = new Organization();
|
||||
organization.setName("Spring Test Organization");
|
||||
organization.setDomain("appsmith-spring-test.com");
|
||||
organization.setWebsite("appsmith.com");
|
||||
|
||||
//Store the organization in case its not present in the database.
|
||||
organizationMono = organizationService.getByName("Spring Test Organization").switchIfEmpty(Mono.defer(() -> organizationService.save(organization)));
|
||||
}
|
||||
|
||||
//Test the update organization flow.
|
||||
|
||||
@Test
|
||||
public void updateInvalidUserWithAnything() {
|
||||
User updateUser = new User();
|
||||
updateUser.setName("Random User whose updates don't matter");
|
||||
|
||||
User existingUser = new User();
|
||||
existingUser.setId("Random-UserId-%Not-In_The-System_For_SUre");
|
||||
|
||||
Mono<User> userMono1 = Mono.just(existingUser).flatMap(user -> userService.update(user.getId(), updateUser));
|
||||
|
||||
StepVerifier.create(userMono1)
|
||||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
|
||||
throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage("Random-UserId-%Not-In_The-System_For_SUre")))
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateUserWithValidOrganization() {
|
||||
User updateUser = new User();
|
||||
//Add valid organization id to the updateUser object.
|
||||
organizationMono
|
||||
.map(organization -> {
|
||||
updateUser.setOrganizationId(organization.getId());
|
||||
return updateUser;
|
||||
}).block();
|
||||
|
||||
Mono<User> userMono1 = userMono.flatMap(user -> userService.update(user.getId(), updateUser));
|
||||
StepVerifier.create(userMono1)
|
||||
.assertNext(updatedUserInRepository -> {
|
||||
assertThat(updatedUserInRepository.getOrganizationId()).isEqualTo(updateUser.getOrganizationId());
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateUserWithInvalidOrganization() {
|
||||
User updateUser = new User();
|
||||
updateUser.setOrganizationId("Random-OrgId-%Not-In_The-System_For_SUre");
|
||||
Mono<User> userMono1 = userMono.flatMap(user -> userService.update(user.getId(), updateUser));
|
||||
StepVerifier.create(userMono1)
|
||||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException &&
|
||||
throwable.getMessage().equals(AppsmithError.INVALID_PARAMETER.getMessage("Random-OrgId-%Not-In_The-System_For_SUre")))
|
||||
.verify();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user