diff --git a/datahub-web-react/src/app/auth/LogIn.tsx b/datahub-web-react/src/app/auth/LogIn.tsx index 012189d6f3..ff46868848 100644 --- a/datahub-web-react/src/app/auth/LogIn.tsx +++ b/datahub-web-react/src/app/auth/LogIn.tsx @@ -71,8 +71,8 @@ export const LogIn: React.VFC = () => { analytics.event({ type: EventType.LogInEvent }); return Promise.resolve(); }) - .catch((error) => { - message.error(`Failed to log in! ${error}`); + .catch((_) => { + message.error(`Failed to log in! An unexpected error occurred.`); }) .finally(() => setLoading(false)); }, diff --git a/datahub-web-react/src/app/auth/ResetCredentials.tsx b/datahub-web-react/src/app/auth/ResetCredentials.tsx index 310a074696..44d69a4b18 100644 --- a/datahub-web-react/src/app/auth/ResetCredentials.tsx +++ b/datahub-web-react/src/app/auth/ResetCredentials.tsx @@ -75,8 +75,8 @@ export const ResetCredentials: React.VFC = () => { analytics.event({ type: EventType.ResetCredentialsEvent }); return Promise.resolve(); }) - .catch((error) => { - message.error(`Failed to log in! ${error}`); + .catch((_) => { + message.error(`Failed to log in!`); }) .finally(() => setLoading(false)); }, diff --git a/datahub-web-react/src/app/auth/SignUp.tsx b/datahub-web-react/src/app/auth/SignUp.tsx index ffda9ce85c..12791855c0 100644 --- a/datahub-web-react/src/app/auth/SignUp.tsx +++ b/datahub-web-react/src/app/auth/SignUp.tsx @@ -90,8 +90,8 @@ export const SignUp: React.VFC = () => { analytics.event({ type: EventType.SignUpEvent, title: values.title }); return Promise.resolve(); }) - .catch((error) => { - message.error(`Failed to log in! ${error}`); + .catch((_) => { + message.error(`Failed to log in! An unexpected error occurred.`); }) .finally(() => setLoading(false)); }, diff --git a/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx b/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx index 34ae20e1f8..2b4f6abb83 100644 --- a/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx +++ b/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx @@ -52,6 +52,7 @@ export function HeaderLinks(props: Props) { const showSettings = true; const showIngestion = isIngestionEnabled && me && me.platformPrivileges.manageIngestion && me.platformPrivileges.manageSecrets; + const showDomains = me?.platformPrivileges.createDomains || me?.platformPrivileges.manageDomains; return ( @@ -82,11 +83,13 @@ export function HeaderLinks(props: Props) { Glossary - - - Domains - - + {showDomains && ( + + + Domains + + + )} } > diff --git a/metadata-service/auth-impl/src/main/java/com/datahub/authentication/user/NativeUserService.java b/metadata-service/auth-impl/src/main/java/com/datahub/authentication/user/NativeUserService.java index 007a22ba1d..e83b89e7d8 100644 --- a/metadata-service/auth-impl/src/main/java/com/datahub/authentication/user/NativeUserService.java +++ b/metadata-service/auth-impl/src/main/java/com/datahub/authentication/user/NativeUserService.java @@ -61,7 +61,7 @@ public class NativeUserService { } public void createNativeUser(@Nonnull String userUrnString, @Nonnull String fullName, @Nonnull String email, - @Nonnull String title, @Nonnull String password, @Nonnull String inviteToken, Authentication authentication) + @Nonnull String title, @Nonnull String password, @Nonnull String inviteToken, @Nonnull Authentication authentication) throws Exception { Objects.requireNonNull(userUrnString, "userUrnSting must not be null!"); Objects.requireNonNull(fullName, "fullName must not be null!"); @@ -69,6 +69,7 @@ public class NativeUserService { Objects.requireNonNull(title, "title must not be null!"); Objects.requireNonNull(password, "password must not be null!"); Objects.requireNonNull(inviteToken, "inviteToken must not be null!"); + Objects.requireNonNull(inviteToken, "authentication must not be null!"); InviteToken inviteTokenAspect = (InviteToken) _entityService.getLatestAspect(Urn.createFromString(GLOBAL_INVITE_TOKEN), @@ -125,7 +126,7 @@ public class NativeUserService { } void updateCorpUserCredentials(@Nonnull Urn userUrn, @Nonnull String password, - Authentication authentication) throws Exception { + @Nonnull Authentication authentication) throws Exception { // Construct corpUserCredentials CorpUserCredentials corpUserCredentials = new CorpUserCredentials(); final byte[] salt = getRandomBytes(SALT_TOKEN_LENGTH); diff --git a/metadata-service/auth-servlet-impl/src/main/java/com/datahub/authentication/AuthServiceController.java b/metadata-service/auth-servlet-impl/src/main/java/com/datahub/authentication/AuthServiceController.java index 60de2de9a8..1e69402481 100644 --- a/metadata-service/auth-servlet-impl/src/main/java/com/datahub/authentication/AuthServiceController.java +++ b/metadata-service/auth-servlet-impl/src/main/java/com/datahub/authentication/AuthServiceController.java @@ -165,11 +165,12 @@ public class AuthServiceController { String titleString = title.asText(); String passwordString = password.asText(); String inviteTokenString = inviteToken.asText(); + Authentication auth = AuthenticationContext.getAuthentication(); log.debug(String.format("Attempting to create credentials for native user %s", userUrnString)); return CompletableFuture.supplyAsync(() -> { try { _nativeUserService.createNativeUser(userUrnString, fullNameString, emailString, titleString, passwordString, - inviteTokenString, AuthenticationContext.getAuthentication()); + inviteTokenString, auth); String response = buildSignUpResponse(); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { @@ -225,11 +226,12 @@ public class AuthServiceController { String userUrnString = userUrn.asText(); String passwordString = password.asText(); String resetTokenString = resetToken.asText(); + Authentication auth = AuthenticationContext.getAuthentication(); log.debug(String.format("Attempting to reset credentials for native user %s", userUrnString)); return CompletableFuture.supplyAsync(() -> { try { _nativeUserService.resetCorpUserCredentials(userUrnString, passwordString, resetTokenString, - AuthenticationContext.getAuthentication()); + auth); String response = buildResetNativeUserCredentialsResponse(); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { diff --git a/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/BootstrapManager.java b/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/BootstrapManager.java index ddcd05b3a8..811ea84bc7 100644 --- a/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/BootstrapManager.java +++ b/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/BootstrapManager.java @@ -2,6 +2,8 @@ package com.linkedin.metadata.boot; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -13,6 +15,7 @@ import org.springframework.stereotype.Component; @Component public class BootstrapManager { + private final ExecutorService _asyncExecutor = Executors.newFixedThreadPool(5); private final List _bootSteps; public BootstrapManager(final List bootSteps) { @@ -42,7 +45,7 @@ public class BootstrapManager { } catch (Exception e) { log.error(String.format("Caught exception while executing bootstrap step %s. Continuing...", step.name()), e); } - }); + }, _asyncExecutor); } } } diff --git a/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/steps/IngestRolesStep.java b/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/steps/IngestRolesStep.java index aa2b12485b..a52c8772b2 100644 --- a/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/steps/IngestRolesStep.java +++ b/metadata-service/factories/src/main/java/com/linkedin/metadata/boot/steps/IngestRolesStep.java @@ -15,6 +15,7 @@ import com.linkedin.mxe.GenericAspect; import com.linkedin.mxe.MetadataChangeProposal; import com.linkedin.policy.DataHubRoleInfo; import java.net.URISyntaxException; +import javax.annotation.Nonnull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ClassPathResource; @@ -25,6 +26,7 @@ import static com.linkedin.metadata.Constants.*; @Slf4j @RequiredArgsConstructor public class IngestRolesStep implements BootstrapStep { + private static final int SLEEP_SECONDS = 60; private final EntityService _entityService; @Override @@ -32,10 +34,19 @@ public class IngestRolesStep implements BootstrapStep { return this.getClass().getSimpleName(); } + @Nonnull + @Override + public ExecutionMode getExecutionMode() { + return ExecutionMode.ASYNC; + } + @Override public void execute() throws Exception { final ObjectMapper mapper = new ObjectMapper(); + // Sleep to ensure deployment process finishes. + Thread.sleep(SLEEP_SECONDS * 1000); + // 0. Execute preflight check to see whether we need to ingest Roles log.info("Ingesting default Roles..."); diff --git a/metadata-service/restli-client/src/main/java/com/linkedin/entity/client/JavaEntityClient.java b/metadata-service/restli-client/src/main/java/com/linkedin/entity/client/JavaEntityClient.java index 26e79d5637..5bd5a5f1dd 100644 --- a/metadata-service/restli-client/src/main/java/com/linkedin/entity/client/JavaEntityClient.java +++ b/metadata-service/restli-client/src/main/java/com/linkedin/entity/client/JavaEntityClient.java @@ -437,8 +437,10 @@ public class JavaEntityClient implements EntityClient { // TODO: Factor out ingest logic into a util that can be accessed by the java client and the resource @SneakyThrows @Override - public String ingestProposal(@Nonnull MetadataChangeProposal metadataChangeProposal, + public String ingestProposal( + @Nonnull final MetadataChangeProposal metadataChangeProposal, @Nonnull final Authentication authentication) throws RemoteInvocationException { + String actorUrnStr = authentication.getActor() != null ? authentication.getActor().toUrnStr() : Constants.UNKNOWN_ACTOR; final AuditStamp auditStamp = new AuditStamp().setTime(_clock.millis()).setActor(Urn.createFromString(actorUrnStr)); diff --git a/metadata-service/war/src/main/resources/boot/policies.json b/metadata-service/war/src/main/resources/boot/policies.json index 19d490823e..fbb9e8ac2f 100644 --- a/metadata-service/war/src/main/resources/boot/policies.json +++ b/metadata-service/war/src/main/resources/boot/policies.json @@ -239,9 +239,6 @@ ] }, "privileges":[ - "MANAGE_INGESTION", - "MANAGE_SECRETS", - "VIEW_ANALYTICS", "GENERATE_PERSONAL_ACCESS_TOKENS", "MANAGE_DOMAINS", "MANAGE_GLOSSARIES", @@ -314,9 +311,7 @@ "urn:li:dataHubRole:Reader" ] }, - "privileges":[ - "VIEW_ANALYTICS" - ], + "privileges":[], "displayName":"Readers - Platform Policy", "description":"Readers can view analytics.", "state":"ACTIVE",