Skip to content
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

[#2238] feat(server): Add the operations for the user #2733

Merged
merged 6 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/
package com.datastrato.gravitino.dto.authorization;

import com.datastrato.gravitino.Audit;
import com.datastrato.gravitino.authorization.User;
import com.datastrato.gravitino.dto.AuditDTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

/** Represents a User Data Transfer Object (DTO). */
public class UserDTO implements User {

@JsonProperty("name")
private String name;

@JsonProperty("audit")
private AuditDTO audit;

@JsonProperty("roles")
private List<String> roles;

/** Default constructor for Jackson deserialization. */
protected UserDTO() {}

/**
* Creates a new instance of UserDTO.
*
* @param name The name of the User DTO.
* @param roles The roles of the User DTO.
* @param audit The audit information of the User DTO.
*/
protected UserDTO(String name, List<String> roles, AuditDTO audit) {
this.name = name;
this.audit = audit;
this.roles = roles;
}

/** @return The name of the User DTO. */
@Override
public String name() {
return name;
}

/**
* The roles of the user. A user can have multiple roles. Every role binds several privileges.
*
* @return The roles of the user.
*/
@Override
public List<String> roles() {
return roles;
}

/** @return The audit information of the User DTO. */
@Override
public Audit auditInfo() {
return audit;
}

/**
* Creates a new Builder for constructing an User DTO.
*
* @return A new Builder instance.
*/
public static Builder builder() {
return new Builder();
}

/**
* Builder class for constructing a UserDTO instance.
*
* @param <S> The type of the builder instance.
*/
public static class Builder<S extends Builder> {

/** The name of the user. */
protected String name;

/** The roles of the user. */
protected List<String> roles = Collections.emptyList();

/** The audit information of the user. */
protected AuditDTO audit;

/**
* Sets the name of the user.
*
* @param name The name of the user.
* @return The builder instance.
*/
public S withName(String name) {
this.name = name;
return (S) this;
}

/**
* Sets the roles of the user.
*
* @param roles The roles of the user.
* @return The builder instance.
*/
public S withRoles(List<String> roles) {
if (roles != null) {
this.roles = roles;
}

return (S) this;
}

/**
* Sets the audit information of the user.
*
* @param audit The audit information of the user.
* @return The builder instance.
*/
public S withAudit(AuditDTO audit) {
this.audit = audit;
return (S) this;
}

/**
* Builds an instance of UserDTO using the builder's properties.
*
* @return An instance of UserDTO.
* @throws IllegalArgumentException If the name or audit are not set.
*/
public UserDTO build() {
Preconditions.checkArgument(StringUtils.isNotBlank(name), "name cannot be null or empty");
Preconditions.checkArgument(audit != null, "audit cannot be null");
return new UserDTO(name, roles, audit);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/
package com.datastrato.gravitino.dto.requests;

import com.datastrato.gravitino.rest.RESTRequest;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.jackson.Jacksonized;
import org.apache.commons.lang3.StringUtils;

/** Represents a request to add a user. */
@Getter
@EqualsAndHashCode
@ToString
@Builder
@Jacksonized
public class UserAddRequest implements RESTRequest {

@JsonProperty("name")
private final String name;

/** Default constructor for UserAddRequest. (Used for Jackson deserialization.) */
public UserAddRequest() {
this(null);
}

/**
* Creates a new UserAddRequest.
*
* @param name The name of the user.
*/
public UserAddRequest(String name) {
super();
this.name = name;
}

/**
* Validates the {@link UserAddRequest} request.
*
* @throws IllegalArgumentException If the request is invalid, this exception is thrown.
*/
@Override
public void validate() throws IllegalArgumentException {
Preconditions.checkArgument(
StringUtils.isNotBlank(name), "\"name\" field is required and cannot be empty");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/
package com.datastrato.gravitino.dto.responses;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.ToString;

/** Represents a response for a remove operation. */
@ToString
@EqualsAndHashCode(callSuper = true)
public class RemoveResponse extends BaseResponse {

@JsonProperty("removed")
private final boolean removed;

/**
* Constructor for RemoveResponse.
*
* @param removed Whether the remove operation was successful.
*/
public RemoveResponse(boolean removed) {
super(0);
this.removed = removed;
}

/** Default constructor for RemoveResponse (used by Jackson deserializer). */
public RemoveResponse() {
super();
this.removed = false;
}

/**
* Returns whether the remove operation was successful.
*
* @return True if the remove operation was successful, otherwise false.
*/
public boolean removed() {
return removed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/
package com.datastrato.gravitino.dto.responses;

import com.datastrato.gravitino.dto.authorization.UserDTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;

/** Represents a response for a user. */
@Getter
@ToString
@EqualsAndHashCode(callSuper = true)
public class UserResponse extends BaseResponse {

@JsonProperty("user")
private final UserDTO user;

/**
* Constructor for UserResponse.
*
* @param user The user data transfer object.
*/
public UserResponse(UserDTO user) {
super(0);
this.user = user;
}

/** Default constructor for UserResponse. (Used for Jackson deserialization.) */
public UserResponse() {
super();
this.user = null;
}

/**
* Validates the response data.
*
* @throws IllegalArgumentException if the name or audit is not set.
*/
@Override
public void validate() throws IllegalArgumentException {
super.validate();

Preconditions.checkArgument(user != null, "user must not be null");
Preconditions.checkArgument(
StringUtils.isNotBlank(user.name()), "user 'name' must not be null and empty");
Preconditions.checkArgument(user.auditInfo() != null, "user 'auditInfo' must not be null");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import com.datastrato.gravitino.Audit;
import com.datastrato.gravitino.Catalog;
import com.datastrato.gravitino.Metalake;
import com.datastrato.gravitino.authorization.User;
import com.datastrato.gravitino.dto.AuditDTO;
import com.datastrato.gravitino.dto.CatalogDTO;
import com.datastrato.gravitino.dto.MetalakeDTO;
import com.datastrato.gravitino.dto.authorization.UserDTO;
import com.datastrato.gravitino.dto.file.FilesetDTO;
import com.datastrato.gravitino.dto.rel.ColumnDTO;
import com.datastrato.gravitino.dto.rel.DistributionDTO;
Expand Down Expand Up @@ -327,6 +329,24 @@ public static IndexDTO toDTO(Index index) {
.build();
}

/**
* Converts a user implementation to a UserDTO.
*
* @param user The user implementation.
* @return The user DTO.
*/
public static UserDTO toDTO(User user) {
if (user instanceof UserDTO) {
return (UserDTO) user;
}

return UserDTO.builder()
.withName(user.name())
.withRoles(user.roles())
.withAudit(toDTO(user.auditInfo()))
.build();
}

/**
* Converts a Expression to an FunctionArg DTO.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.datastrato.gravitino.dto.AuditDTO;
import com.datastrato.gravitino.dto.CatalogDTO;
import com.datastrato.gravitino.dto.MetalakeDTO;
import com.datastrato.gravitino.dto.authorization.UserDTO;
import com.datastrato.gravitino.dto.rel.ColumnDTO;
import com.datastrato.gravitino.dto.rel.SchemaDTO;
import com.datastrato.gravitino.dto.rel.TableDTO;
Expand Down Expand Up @@ -223,4 +224,19 @@ void testOAuthErrorException() throws IllegalArgumentException {
OAuth2ErrorResponse response = new OAuth2ErrorResponse();
assertThrows(IllegalArgumentException.class, () -> response.validate());
}

@Test
void testUserResponse() throws IllegalArgumentException {
AuditDTO audit =
AuditDTO.builder().withCreator("creator").withCreateTime(Instant.now()).build();
UserDTO user = UserDTO.builder().withName("user1").withAudit(audit).build();
UserResponse response = new UserResponse(user);
response.validate(); // No exception thrown
}

@Test
void testUserResponseException() throws IllegalArgumentException {
UserResponse user = new UserResponse();
assertThrows(IllegalArgumentException.class, () -> user.validate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package com.datastrato.gravitino.server;

import com.datastrato.gravitino.GravitinoEnv;
import com.datastrato.gravitino.authorization.AccessControlManager;
import com.datastrato.gravitino.catalog.CatalogManager;
import com.datastrato.gravitino.catalog.FilesetOperationDispatcher;
import com.datastrato.gravitino.catalog.SchemaOperationDispatcher;
Expand Down Expand Up @@ -75,6 +76,7 @@ private void initializeRestApi() {
protected void configure() {
bind(gravitinoEnv.metalakesManager()).to(MetalakeManager.class).ranked(1);
bind(gravitinoEnv.catalogManager()).to(CatalogManager.class).ranked(1);
bind(gravitinoEnv.accessControlManager()).to(AccessControlManager.class).ranked(1);
bind(gravitinoEnv.schemaOperationDispatcher())
.to(SchemaOperationDispatcher.class)
.ranked(1);
Expand Down
Loading
Loading