Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d0d28cc7e6 | |||
| 2d1260c01b | |||
| 06da6a2cc6 | |||
| 858a22f82e | |||
| 3c126ddfd4 | |||
| 2b98e6f177 | |||
| 20036b6a74 | |||
| 396cbd6bd3 | |||
| 71ea16ff69 | |||
| 45331be166 | |||
| beb7c14adb | |||
| d33571dde3 | |||
| 53a7d1b66c |
@@ -18,7 +18,11 @@
|
||||
<mat-icon>edit</mat-icon>
|
||||
Edit
|
||||
</button>
|
||||
<button mat-icon-button aria-label="Delete Contact">
|
||||
<button
|
||||
mat-icon-button
|
||||
aria-label="Delete Contact"
|
||||
(click)="deleteContact()"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ export class ContactDetailsComponent {
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this._snackBar.open(err.error);
|
||||
},
|
||||
complete: () => {
|
||||
this.goBack();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,18 @@
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
@if((userDataService.userData()?.globalRole || 'NONE') !== "NONE") {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>ICANN Referral Email: </mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[(ngModel)]="registrarInEdit.icannReferralEmail"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<button mat-flat-button color="primary" type="submit">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
Registrar,
|
||||
RegistrarService,
|
||||
} from 'src/app/registrar/registrar.service';
|
||||
import { UserDataService } from 'src/app/shared/services/userData.service';
|
||||
import { WhoisService } from './whois.service';
|
||||
|
||||
@Component({
|
||||
@@ -30,6 +31,7 @@ export default class WhoisEditComponent {
|
||||
registrarInEdit: Registrar | undefined;
|
||||
|
||||
constructor(
|
||||
public userDataService: UserDataService,
|
||||
public whoisService: WhoisService,
|
||||
public registrarService: RegistrarService,
|
||||
private _snackBar: MatSnackBar
|
||||
|
||||
@@ -77,6 +77,7 @@ public class CloudTasksUtils implements Serializable {
|
||||
@Config("projectId") String projectId,
|
||||
@Config("locationId") String locationId,
|
||||
@Config("oauthClientId") String oauthClientId,
|
||||
// Note that this has to be a service account, due to limitations of the Cloud Tasks API.
|
||||
@ApplicationDefaultCredential GoogleCredentialsBundle credential,
|
||||
SerializableCloudTasksClient client) {
|
||||
this.retrier = retrier;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<delete>
|
||||
<domain:delete
|
||||
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||
<domain:name>%DOMAIN%</domain:name>
|
||||
</domain:delete>
|
||||
</delete>
|
||||
<extension>
|
||||
<metadata:metadata xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
|
||||
<metadata:reason>Non-renewing domain has reached expiration date.</metadata:reason>
|
||||
<metadata:requestedByRegistrar>false</metadata:requestedByRegistrar>
|
||||
</metadata:metadata>
|
||||
</extension>
|
||||
<clTRID>ABC-12345</clTRID>
|
||||
</command>
|
||||
</epp>
|
||||
@@ -32,7 +32,6 @@ import com.google.common.collect.Streams;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -48,9 +47,7 @@ import google.registry.util.CidrAddressBlock;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -271,29 +268,21 @@ public final class OteAccountBuilder {
|
||||
Optional<String> groupEmailAddress, CloudTasksUtils cloudTasksUtils, IamClient iamClient) {
|
||||
for (User user : users) {
|
||||
User.grantIapPermission(
|
||||
user.getEmailAddress(), groupEmailAddress, cloudTasksUtils, iamClient);
|
||||
user.getEmailAddress(), groupEmailAddress, cloudTasksUtils, null, iamClient);
|
||||
}
|
||||
}
|
||||
|
||||
/** Saves all the OT&E entities we created. */
|
||||
private void saveAllEntities() {
|
||||
ImmutableList<Tld> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||
Map<String, User> existingUsers = new HashMap<>();
|
||||
|
||||
users.forEach(
|
||||
user ->
|
||||
UserDao.loadUser(user.getEmailAddress())
|
||||
.ifPresent(
|
||||
existingUser ->
|
||||
existingUsers.put(existingUser.getEmailAddress(), existingUser)));
|
||||
|
||||
if (!replaceExisting) {
|
||||
checkState(existingUsers.isEmpty(), "Found existing users: %s", existingUsers);
|
||||
}
|
||||
|
||||
tm().transact(
|
||||
() -> {
|
||||
if (!replaceExisting) {
|
||||
ImmutableMap<String, User> existingUsers =
|
||||
tm().loadByEntitiesIfPresent(users).stream()
|
||||
.collect(toImmutableMap(User::getEmailAddress, u -> u));
|
||||
checkState(existingUsers.isEmpty(), "Found existing users: %s", existingUsers);
|
||||
|
||||
ImmutableList<VKey<? extends ImmutableObject>> keys =
|
||||
Streams.concat(
|
||||
registries.stream().map(tld -> Tld.createVKey(tld.getTldStr())),
|
||||
@@ -317,16 +306,7 @@ public final class OteAccountBuilder {
|
||||
tm().putAll(registrars);
|
||||
});
|
||||
|
||||
for (User user : users) {
|
||||
String email = user.getEmailAddress();
|
||||
if (existingUsers.containsKey(email)) {
|
||||
// Note that other roles for the existing user are reset. We do this instead of simply
|
||||
// saving the new user is that UserDao does not allow us to save the new user with the same
|
||||
// email as the existing user.
|
||||
user = existingUsers.get(email).asBuilder().setUserRoles(user.getUserRoles()).build();
|
||||
}
|
||||
UserDao.saveUser(user);
|
||||
}
|
||||
tm().transact(() -> tm().putAll(ImmutableList.copyOf(users)));
|
||||
}
|
||||
|
||||
private Registrar addAllowedTld(Registrar registrar) {
|
||||
|
||||
@@ -63,7 +63,8 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
|
||||
public enum FeatureName {
|
||||
TEST_FEATURE,
|
||||
MINIMUM_DATASET_CONTACTS_OPTIONAL,
|
||||
MINIMUM_DATASET_CONTACTS_PROHIBITED
|
||||
MINIMUM_DATASET_CONTACTS_PROHIBITED,
|
||||
NEW_CONSOLE
|
||||
}
|
||||
|
||||
/** The name of the flag/feature. */
|
||||
|
||||
@@ -14,33 +14,36 @@
|
||||
|
||||
package google.registry.model.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.tools.server.UpdateUserGroupAction.GROUP_UPDATE_QUEUE;
|
||||
|
||||
import com.google.cloud.tasks.v2.Task;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.tools.IamClient;
|
||||
import google.registry.tools.ServiceConnection;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import google.registry.tools.server.UpdateUserGroupAction.Mode;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/** A console user, either a registry employee or a registrar partner. */
|
||||
@Embeddable
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "emailAddress", name = "user_email_address_idx")})
|
||||
@Table
|
||||
public class User extends UserBase {
|
||||
|
||||
public static final String IAP_SECURED_WEB_APP_USER_ROLE = "roles/iap.httpsResourceAccessor";
|
||||
@@ -55,18 +58,30 @@ public class User extends UserBase {
|
||||
public static void grantIapPermission(
|
||||
String emailAddress,
|
||||
Optional<String> groupEmailAddress,
|
||||
CloudTasksUtils cloudTasksUtils,
|
||||
@Nullable CloudTasksUtils cloudTasksUtils,
|
||||
@Nullable ServiceConnection connection,
|
||||
IamClient iamClient) {
|
||||
if (RegistryEnvironment.isInTestServer()) {
|
||||
return;
|
||||
}
|
||||
checkArgument(
|
||||
cloudTasksUtils != null || connection != null,
|
||||
"At least one of cloudTasksUtils or connection must be set");
|
||||
checkArgument(
|
||||
cloudTasksUtils == null || connection == null,
|
||||
"Only one of cloudTasksUtils or connection can be set");
|
||||
if (groupEmailAddress.isEmpty()) {
|
||||
logger.atInfo().log("Granting IAP role to user %s", emailAddress);
|
||||
iamClient.addBinding(emailAddress, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
} else {
|
||||
logger.atInfo().log("Adding %s to group %s", emailAddress, groupEmailAddress.get());
|
||||
modifyGroupMembershipAsync(
|
||||
emailAddress, groupEmailAddress.get(), cloudTasksUtils, UpdateUserGroupAction.Mode.ADD);
|
||||
if (cloudTasksUtils != null) {
|
||||
modifyGroupMembershipAsync(
|
||||
emailAddress, groupEmailAddress.get(), cloudTasksUtils, UpdateUserGroupAction.Mode.ADD);
|
||||
} else {
|
||||
modifyGroupMembershipSync(
|
||||
emailAddress, groupEmailAddress.get(), connection, UpdateUserGroupAction.Mode.ADD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,18 +94,29 @@ public class User extends UserBase {
|
||||
public static void revokeIapPermission(
|
||||
String emailAddress,
|
||||
Optional<String> groupEmailAddress,
|
||||
CloudTasksUtils cloudTasksUtils,
|
||||
@Nullable CloudTasksUtils cloudTasksUtils,
|
||||
@Nullable ServiceConnection connection,
|
||||
IamClient iamClient) {
|
||||
if (RegistryEnvironment.isInTestServer()) {
|
||||
return;
|
||||
}
|
||||
checkArgument(
|
||||
cloudTasksUtils != null || connection != null,
|
||||
"At least one of cloudTasksUtils or connection must be set");
|
||||
checkArgument(
|
||||
cloudTasksUtils == null || connection == null,
|
||||
"Only one of cloudTasksUtils or connection can be set");
|
||||
if (groupEmailAddress.isEmpty()) {
|
||||
logger.atInfo().log("Removing IAP role from user %s", emailAddress);
|
||||
iamClient.removeBinding(emailAddress, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
} else {
|
||||
logger.atInfo().log("Removing %s from group %s", emailAddress, groupEmailAddress.get());
|
||||
modifyGroupMembershipAsync(
|
||||
emailAddress, groupEmailAddress.get(), cloudTasksUtils, Mode.REMOVE);
|
||||
if (cloudTasksUtils != null) {
|
||||
modifyGroupMembershipAsync(
|
||||
emailAddress, groupEmailAddress.get(), cloudTasksUtils, Mode.REMOVE);
|
||||
} else {
|
||||
modifyGroupMembershipSync(emailAddress, groupEmailAddress.get(), connection, Mode.REMOVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,12 +139,30 @@ public class User extends UserBase {
|
||||
cloudTasksUtils.enqueue(GROUP_UPDATE_QUEUE, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
private static void modifyGroupMembershipSync(
|
||||
String userEmailAddress, String groupEmailAddress, ServiceConnection connection, Mode mode) {
|
||||
try {
|
||||
connection.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
userEmailAddress,
|
||||
"groupEmailAddress",
|
||||
groupEmailAddress,
|
||||
"groupUpdateMode",
|
||||
mode.name()),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot send request to server", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Override
|
||||
@Access(AccessType.PROPERTY)
|
||||
public Long getId() {
|
||||
return super.getId();
|
||||
public String getEmailAddress() {
|
||||
return super.getEmailAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,7 +172,7 @@ public class User extends UserBase {
|
||||
|
||||
@Override
|
||||
public VKey<User> createVKey() {
|
||||
return VKey.create(User.class, getId());
|
||||
return VKey.create(User.class, getEmailAddress());
|
||||
}
|
||||
|
||||
/** Builder for constructing immutable {@link User} objects. */
|
||||
|
||||
@@ -49,12 +49,8 @@ public class UserBase extends UpdateAutoTimestampEntity implements Buildable {
|
||||
|
||||
private static final long serialVersionUID = 6936728603828566721L;
|
||||
|
||||
/** Autogenerated unique ID of this user. */
|
||||
@Transient private Long id;
|
||||
|
||||
/** Email address of the user in question. */
|
||||
@Column(nullable = false)
|
||||
String emailAddress;
|
||||
@Transient String emailAddress;
|
||||
|
||||
/** Optional external email address to use for registry lock confirmation emails. */
|
||||
@Column String registryLockEmailAddress;
|
||||
@@ -72,22 +68,17 @@ public class UserBase extends UpdateAutoTimestampEntity implements Buildable {
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user ID.
|
||||
* Sets the user email address.
|
||||
*
|
||||
* <p>This should only be used for restoring the user id of an object being loaded in a PostLoad
|
||||
* method (effectively, when it is still under construction by Hibernate). In all other cases, the
|
||||
* object should be regarded as immutable and changes should go through a Builder.
|
||||
* <p>This should only be used for restoring an object being loaded in a PostLoad method
|
||||
* (effectively, when it is still under construction by Hibernate). In all other cases, the object
|
||||
* should be regarded as immutable and changes should go through a Builder.
|
||||
*
|
||||
* <p>In addition to this special case use, this method must exist to satisfy Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
void setId(Long id) {
|
||||
this.id = id;
|
||||
void setEmailAddress(String emailAddress) {
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
public String getEmailAddress() {
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// 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 google.registry.model.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/** Data access object for {@link User} objects to simplify saving and retrieval. */
|
||||
public class UserDao {
|
||||
|
||||
/** Retrieves the one user with this email address if it exists. */
|
||||
public static Optional<User> loadUser(String emailAddress) {
|
||||
return tm().transact(
|
||||
() ->
|
||||
tm().query("FROM User WHERE emailAddress = :emailAddress", User.class)
|
||||
.setParameter("emailAddress", emailAddress)
|
||||
.getResultStream()
|
||||
.findFirst());
|
||||
}
|
||||
|
||||
/** Saves the given user, checking that no existing user already exists with this email. */
|
||||
public static void saveUser(User user) {
|
||||
tm().transact(
|
||||
() -> {
|
||||
// Check for an existing user (the unique constraint protects us, but this gives a
|
||||
// nicer exception)
|
||||
Optional<User> maybeSavedUser = loadUser(user.getEmailAddress());
|
||||
if (maybeSavedUser.isPresent()) {
|
||||
User savedUser = maybeSavedUser.get();
|
||||
checkArgument(
|
||||
savedUser.getId().equals(user.getId()),
|
||||
String.format(
|
||||
"Attempted save of User with email address %s and ID %s, user with that"
|
||||
+ " email already exists with ID %s",
|
||||
user.getEmailAddress(), user.getId(), savedUser.getId()));
|
||||
}
|
||||
tm().put(user);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,8 @@ public class UserUpdateHistory extends ConsoleUpdateHistory {
|
||||
|
||||
UserBase user;
|
||||
|
||||
// This field exists so that it's populated in the SQL table
|
||||
@Column(nullable = false, name = "userId")
|
||||
Long id;
|
||||
@Column(nullable = false, name = "emailAddress")
|
||||
String emailAddress;
|
||||
|
||||
public UserBase getUser() {
|
||||
return user;
|
||||
@@ -48,7 +47,7 @@ public class UserUpdateHistory extends ConsoleUpdateHistory {
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
user.setId(id);
|
||||
user.setEmailAddress(emailAddress);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
@@ -79,7 +78,7 @@ public class UserUpdateHistory extends ConsoleUpdateHistory {
|
||||
|
||||
public Builder setUser(User user) {
|
||||
getInstance().user = user;
|
||||
getInstance().id = user.getId();
|
||||
getInstance().emailAddress = user.getEmailAddress();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.request.auth;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.api.client.json.webtoken.JsonWebSignature;
|
||||
import com.google.auth.oauth2.TokenVerifier;
|
||||
@@ -23,7 +24,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.auth.AuthModule.IapOidc;
|
||||
import google.registry.request.auth.AuthModule.RegularOidc;
|
||||
import google.registry.request.auth.AuthModule.RegularOidcFallback;
|
||||
@@ -117,7 +118,8 @@ public abstract class OidcTokenAuthenticationMechanism implements Authentication
|
||||
logger.atWarning().log("No email address from the OIDC token:\n%s", token.getPayload());
|
||||
return AuthResult.NOT_AUTHENTICATED;
|
||||
}
|
||||
Optional<User> maybeUser = UserDao.loadUser(email);
|
||||
Optional<User> maybeUser =
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(User.class, email)));
|
||||
if (maybeUser.isPresent()) {
|
||||
return AuthResult.createUser(maybeUser.get());
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.tools.params.KeyValueMapParameter.StringToRegistrarRoleMap;
|
||||
import java.util.Optional;
|
||||
@@ -95,8 +94,6 @@ public abstract class CreateOrUpdateUserCommand extends ConfirmingCommand {
|
||||
builder.setRegistryLockEmailAddress(registryLockEmailAddress);
|
||||
}
|
||||
}
|
||||
|
||||
User newUser = builder.build();
|
||||
UserDao.saveUser(newUser);
|
||||
tm().put(builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,24 @@ package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.console.User.grantIapPermission;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Command to create a new User. */
|
||||
@Parameters(separators = " =", commandDescription = "Update a user account")
|
||||
public class CreateUserCommand extends CreateOrUpdateUserCommand {
|
||||
public class CreateUserCommand extends CreateOrUpdateUserCommand implements CommandWithConnection {
|
||||
|
||||
private ServiceConnection connection;
|
||||
|
||||
@Inject IamClient iamClient;
|
||||
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@Inject
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||
Optional<String> maybeGroupEmailAddress;
|
||||
@@ -41,14 +41,20 @@ public class CreateUserCommand extends CreateOrUpdateUserCommand {
|
||||
@Nullable
|
||||
@Override
|
||||
User getExistingUser(String email) {
|
||||
checkArgument(UserDao.loadUser(email).isEmpty(), "A user with email %s already exists", email);
|
||||
checkArgument(
|
||||
!tm().exists(VKey.create(User.class, email)), "A user with email %s already exists", email);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String execute() throws Exception {
|
||||
String ret = super.execute();
|
||||
grantIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||
grantIapPermission(email, maybeGroupEmailAddress, null, connection, iamClient);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(ServiceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,27 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.api.client.util.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Deletes a {@link User}. */
|
||||
@Parameters(separators = " =", commandDescription = "Delete a user account")
|
||||
public class DeleteUserCommand extends ConfirmingCommand {
|
||||
public class DeleteUserCommand extends ConfirmingCommand implements CommandWithConnection {
|
||||
|
||||
private ServiceConnection connection;
|
||||
|
||||
@Inject IamClient iamClient;
|
||||
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@Inject
|
||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||
Optional<String> maybeGroupEmailAddress;
|
||||
@@ -47,7 +46,9 @@ public class DeleteUserCommand extends ConfirmingCommand {
|
||||
@Override
|
||||
protected String prompt() {
|
||||
checkArgumentNotNull(email, "Email must be provided");
|
||||
checkArgumentPresent(UserDao.loadUser(email), "Email does not correspond to a valid user");
|
||||
checkArgument(
|
||||
tm().transact(() -> tm().exists(VKey.create(User.class, email))),
|
||||
"Email does not correspond to a valid user");
|
||||
return String.format("Delete user with email %s?", email);
|
||||
}
|
||||
|
||||
@@ -55,11 +56,16 @@ public class DeleteUserCommand extends ConfirmingCommand {
|
||||
protected String execute() throws Exception {
|
||||
tm().transact(
|
||||
() -> {
|
||||
Optional<User> optionalUser = UserDao.loadUser(email);
|
||||
checkArgumentPresent(optionalUser, "Email no longer corresponds to a valid user");
|
||||
tm().delete(optionalUser.get());
|
||||
VKey<User> key = VKey.create(User.class, email);
|
||||
checkArgument(tm().exists(key), "Email no longer corresponds to a valid user");
|
||||
tm().delete(key);
|
||||
});
|
||||
User.revokeIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||
User.revokeIapPermission(email, maybeGroupEmailAddress, null, connection, iamClient);
|
||||
return String.format("Deleted user with email %s", email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(ServiceConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.List;
|
||||
|
||||
/** Command to display one or more users. */
|
||||
@@ -29,11 +31,14 @@ public class GetUserCommand implements Command {
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
for (String emailAddress : mainParameters) {
|
||||
System.out.println(
|
||||
UserDao.loadUser(emailAddress)
|
||||
.map(User::toString)
|
||||
.orElse(String.format("No user with email address %s", emailAddress)));
|
||||
}
|
||||
tm().transact(
|
||||
() -> {
|
||||
for (String emailAddress : mainParameters) {
|
||||
System.out.println(
|
||||
tm().loadByKeyIfPresent(VKey.create(User.class, emailAddress))
|
||||
.map(User::toString)
|
||||
.orElse(String.format("No user with email address %s", emailAddress)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,20 +14,20 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import javax.annotation.Nullable;
|
||||
import google.registry.persistence.VKey;
|
||||
|
||||
/** Updates a user, assuming that the user in question already exists. */
|
||||
@Parameters(separators = " =", commandDescription = "Update a user account")
|
||||
public class UpdateUserCommand extends CreateOrUpdateUserCommand {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
User getExistingUser(String email) {
|
||||
return checkArgumentPresent(UserDao.loadUser(email), "User %s not found", email);
|
||||
return checkArgumentPresent(
|
||||
tm().loadByKeyIfPresent(VKey.create(User.class, email)), "User %s not found", email);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.model.common.FeatureFlag.FeatureName.NEW_CONSOLE;
|
||||
import static google.registry.model.common.FeatureFlag.isActiveNow;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
@@ -88,7 +91,10 @@ public abstract class ConsoleApiAction implements Runnable {
|
||||
!GlobalRole.NONE.equals(userRoles.getGlobalRole())
|
||||
|| userRoles.hasPermission(
|
||||
registryAdminClientId, ConsolePermission.VIEW_REGISTRAR_DETAILS);
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.UNITTEST && !hasGlobalOrTestingRole) {
|
||||
|
||||
if (!hasGlobalOrTestingRole
|
||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST
|
||||
&& tm().transact(() -> !isActiveNow(NEW_CONSOLE))) {
|
||||
try {
|
||||
consoleApiParams.response().sendRedirect(ConsoleUiAction.PATH);
|
||||
return;
|
||||
|
||||
@@ -60,7 +60,7 @@ public class ConsoleRegistryLockVerifyAction extends ConsoleApiAction {
|
||||
RegistryLock lock =
|
||||
domainLockUtils.verifyVerificationCode(lockVerificationCode, user.getUserRoles().isAdmin());
|
||||
RegistryLockAction action =
|
||||
lock.getLockCompletionTime().isPresent()
|
||||
lock.getUnlockCompletionTime().isPresent()
|
||||
? RegistryLockAction.UNLOCKED
|
||||
: RegistryLockAction.LOCKED;
|
||||
RegistryLockVerificationResponse lockResponse =
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.ui.server.console.settings;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
@@ -30,6 +31,7 @@ import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
||||
import google.registry.ui.server.console.ConsoleApiAction;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -65,10 +67,10 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
checkArgument(registrar.isPresent(), "'registrar' parameter is not present");
|
||||
checkPermission(
|
||||
user, registrar.get().getRegistrarId(), ConsolePermission.EDIT_REGISTRAR_DETAILS);
|
||||
tm().transact(() -> loadAndModifyRegistrar(registrar.get()));
|
||||
tm().transact(() -> loadAndModifyRegistrar(registrar.get(), user));
|
||||
}
|
||||
|
||||
private void loadAndModifyRegistrar(Registrar providedRegistrar) {
|
||||
private void loadAndModifyRegistrar(Registrar providedRegistrar, User user) {
|
||||
Registrar savedRegistrar;
|
||||
try {
|
||||
// reload to make sure the object has all the correct fields
|
||||
@@ -78,6 +80,15 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
return;
|
||||
}
|
||||
|
||||
// icannReferralEmail can't be updated by partners, only by global users with
|
||||
// EDIT_REGISTRAR_DETAILS permission
|
||||
if (!Objects.equals(
|
||||
savedRegistrar.getIcannReferralEmail(), providedRegistrar.getIcannReferralEmail())
|
||||
&& !user.getUserRoles().hasGlobalPermission(ConsolePermission.EDIT_REGISTRAR_DETAILS)) {
|
||||
setFailedResponse(
|
||||
"Icann Referral Email update is not permitted for this user", SC_BAD_REQUEST);
|
||||
}
|
||||
|
||||
Registrar newRegistrar =
|
||||
savedRegistrar
|
||||
.asBuilder()
|
||||
@@ -86,6 +97,8 @@ public class WhoisRegistrarFieldsAction extends ConsoleApiAction {
|
||||
.setLocalizedAddress(providedRegistrar.getLocalizedAddress())
|
||||
.setPhoneNumber(providedRegistrar.getPhoneNumber())
|
||||
.setFaxNumber(providedRegistrar.getFaxNumber())
|
||||
.setIcannReferralEmail(providedRegistrar.getIcannReferralEmail())
|
||||
.setEmailAddress(providedRegistrar.getEmailAddress())
|
||||
.build();
|
||||
tm().put(newRegistrar);
|
||||
sendExternalUpdatesIfNecessary(
|
||||
|
||||
@@ -30,7 +30,6 @@ import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
@@ -260,10 +259,10 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
||||
"Registrar with client ID %s already exists",
|
||||
registrar.getRegistrarId());
|
||||
tm().put(registrar);
|
||||
tm().put(user);
|
||||
});
|
||||
UserDao.saveUser(user);
|
||||
User.grantIapPermission(
|
||||
user.getEmailAddress(), maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||
user.getEmailAddress(), maybeGroupEmailAddress, cloudTasksUtils, null, iamClient);
|
||||
data.put("password", password);
|
||||
data.put("passcode", phonePasscode);
|
||||
|
||||
|
||||
@@ -14,10 +14,13 @@
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.ADMIN;
|
||||
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER;
|
||||
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_PERMANENT_REDIRECT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
@@ -26,6 +29,8 @@ import com.google.common.flogger.FluentLogger;
|
||||
import com.google.template.soy.data.SoyMapData;
|
||||
import com.google.template.soy.tofu.SoyTofu;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
@@ -35,8 +40,10 @@ import google.registry.request.auth.AuthenticatedRegistrarAccessor.Role;
|
||||
import google.registry.ui.server.SoyTemplateUtils;
|
||||
import google.registry.ui.soy.registrar.ConsoleSoyInfo;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Action that serves Registrar Console single HTML page (SPA). */
|
||||
@@ -100,6 +107,7 @@ public final class ConsoleUiAction extends HtmlAction {
|
||||
soyMapData.put("announcementsEmail", announcementsEmail);
|
||||
soyMapData.put("supportPhoneNumber", supportPhoneNumber);
|
||||
soyMapData.put("technicalDocsUrl", technicalDocsUrl);
|
||||
|
||||
if (!enabled) {
|
||||
response.setStatus(SC_SERVICE_UNAVAILABLE);
|
||||
response.setPayload(
|
||||
@@ -111,9 +119,35 @@ public final class ConsoleUiAction extends HtmlAction {
|
||||
.render());
|
||||
return;
|
||||
}
|
||||
|
||||
// Set permanent redirect to the new console for tech support
|
||||
if (isNullOrEmpty(req.getParameter("redirect"))
|
||||
&& Stream.of(GlobalRole.SUPPORT_LEAD, GlobalRole.SUPPORT_AGENT)
|
||||
.anyMatch(
|
||||
globalRole ->
|
||||
globalRole.equals(authResult.user().get().getUserRoles().getGlobalRole()))) {
|
||||
response.setStatus(SC_PERMANENT_REDIRECT);
|
||||
try {
|
||||
response.sendRedirect("/console");
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableSetMultimap<String, Role> roleMap = registrarAccessor.getAllRegistrarIdsWithRoles();
|
||||
soyMapData.put("allClientIds", roleMap.keySet());
|
||||
soyMapData.put("environment", RegistryEnvironment.get().toString());
|
||||
boolean newConsole =
|
||||
tm().transact(
|
||||
() ->
|
||||
FeatureFlag.getUncached(FeatureFlag.FeatureName.NEW_CONSOLE)
|
||||
.map(
|
||||
flag ->
|
||||
flag.getStatus(tm().getTransactionTime())
|
||||
.equals(FeatureFlag.FeatureStatus.ACTIVE))
|
||||
.orElse(false));
|
||||
soyMapData.put("includeDeprecationWarning", newConsole);
|
||||
// We set the initial value to the value that will show if guessClientId throws.
|
||||
String clientId = "<null>";
|
||||
try {
|
||||
|
||||
@@ -261,7 +261,7 @@ li.kd-menulistitem {
|
||||
top: 136px;
|
||||
left: 173px;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
width: calc(100% - 173px);
|
||||
margin: 0;
|
||||
padding: 25px 0 1em 0;
|
||||
overflow-y: scroll !important;
|
||||
@@ -296,3 +296,31 @@ li.kd-menulistitem {
|
||||
.reg-select {
|
||||
margin-left: 23px;
|
||||
}
|
||||
|
||||
div#reg-deprecation-warning {
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
background-color: #ba2a1a;
|
||||
font-size: 0.6svw;
|
||||
}
|
||||
|
||||
div#reg-deprecation-warning h1 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div#reg-deprecation-warning a {
|
||||
color: #add8e6;
|
||||
}
|
||||
|
||||
div#reg-accessing-as-role {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
div#reg-deprecation-warning {
|
||||
font-size: 0.85vw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
{@param technicalDocsUrl: string}
|
||||
{@param environment: string}
|
||||
{@param analyticsConfig: [googleAnalyticsId: string|null]}
|
||||
{@param includeDeprecationWarning: bool}
|
||||
|
||||
{call registry.soy.console.header}
|
||||
{param app: 'registrar' /}
|
||||
@@ -45,7 +46,7 @@
|
||||
{call registry.soy.console.googlebar data="all" /}
|
||||
<div id="reg-app" lang="en-US">
|
||||
<div id="reg-appbar" class="{css('kd-appbar')}">
|
||||
<div class="{css('kd-description')}">
|
||||
<div id="reg-accessing-as-role" class="{css('kd-description')}">
|
||||
Accessing <span class="{css('kd-value')}">{$clientId}</span> as{sp}
|
||||
{if $isOwner}<span class="{css('kd-value')}">Owner</span>{/if}
|
||||
{if $isAdmin}<span class="{css('kd-value')}">Admin</span>{/if}
|
||||
@@ -53,6 +54,13 @@
|
||||
{sp}(Switch registrar: {call .clientIdSelect_ data="all" /})
|
||||
{/if}
|
||||
</div>
|
||||
{if $includeDeprecationWarning}
|
||||
<div id="reg-deprecation-warning">
|
||||
<h1>Note: this console is deprecated and will be deactivated in October 2024.
|
||||
Please use the <a href="/console">new console</a> instead.
|
||||
</h1>
|
||||
</div>
|
||||
{/if}
|
||||
<div id="reg-app-buttons" class="{css('kd-buttonbar')} {css('left')}"></div>
|
||||
</div>
|
||||
{call .navbar_ data="all" /}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static google.registry.persistence.transaction.JpaTransactionManagerExten
|
||||
import static google.registry.testing.CertificateSamples.SAMPLE_CERT;
|
||||
import static google.registry.testing.CertificateSamples.SAMPLE_CERT_HASH;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadByKeyIfPresent;
|
||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||
import static google.registry.testing.DatabaseHelper.persistSimpleResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -36,10 +37,10 @@ import com.google.common.collect.ImmutableList;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.model.tld.Tld.TldState;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
@@ -106,7 +107,7 @@ public final class OteAccountBuilderTest {
|
||||
}
|
||||
|
||||
public static void verifyUser(String registrarId, String email) {
|
||||
Optional<User> maybeUser = UserDao.loadUser(email);
|
||||
Optional<User> maybeUser = loadByKeyIfPresent(VKey.create(User.class, email));
|
||||
assertThat(maybeUser).isPresent();
|
||||
assertThat(maybeUser.get().getUserRoles().getRegistrarRoles().get(registrarId))
|
||||
.isEqualTo(RegistrarRole.ACCOUNT_MANAGER);
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// 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 google.registry.model.console;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.model.EntityTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests for {@link UserDao}. */
|
||||
public class UserDaoTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testSuccess_saveAndRetrieve() {
|
||||
User user1 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
User user2 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("foo@bar.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
UserDao.saveUser(user1);
|
||||
UserDao.saveUser(user2);
|
||||
assertAboutImmutableObjects()
|
||||
.that(user1)
|
||||
.isEqualExceptFields(UserDao.loadUser("email@email.com").get(), "id", "updateTimestamp");
|
||||
assertAboutImmutableObjects()
|
||||
.that(user2)
|
||||
.isEqualExceptFields(UserDao.loadUser("foo@bar.com").get(), "id", "updateTimestamp");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_absentUser() {
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
UserDao.saveUser(user);
|
||||
User fromDb = UserDao.loadUser("email@email.com").get();
|
||||
// nonexistent one should never exist
|
||||
assertThat(UserDao.loadUser("nonexistent@email.com")).isEmpty();
|
||||
// now try deleting the one that does exist
|
||||
tm().transact(() -> tm().delete(fromDb));
|
||||
assertThat(UserDao.loadUser("email@email.com")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_sameEmail() {
|
||||
User user1 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
User user2 =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build())
|
||||
.build();
|
||||
UserDao.saveUser(user1);
|
||||
assertThrows(IllegalArgumentException.class, () -> UserDao.saveUser(user2));
|
||||
assertAboutImmutableObjects()
|
||||
.that(user1)
|
||||
.isEqualExceptFields(UserDao.loadUser("email@email.com").get(), "id", "updateTimestamp");
|
||||
}
|
||||
}
|
||||
@@ -21,15 +21,20 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.batch.CloudTasksUtils;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.tools.IamClient;
|
||||
import google.registry.tools.ServiceConnection;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -57,6 +62,34 @@ public class UserTest extends EntityTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_asyncAndSyncModeConflict() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> User.grantIapPermission("email@example.com", Optional.empty(), null, null, null));
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
User.grantIapPermission(
|
||||
"email@example.com",
|
||||
Optional.empty(),
|
||||
mock(CloudTasksUtils.class),
|
||||
mock(ServiceConnection.class),
|
||||
null));
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> User.revokeIapPermission("email@example.com", Optional.empty(), null, null, null));
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
User.revokeIapPermission(
|
||||
"email@example.com",
|
||||
Optional.empty(),
|
||||
mock(CloudTasksUtils.class),
|
||||
mock(ServiceConnection.class),
|
||||
null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_badInputs() {
|
||||
User.Builder builder = new User.Builder();
|
||||
@@ -116,19 +149,20 @@ public class UserTest extends EntityTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGrantIapPermission() {
|
||||
void testGrantIapPermissionAsync() {
|
||||
CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
IamClient iamClient = mock(IamClient.class);
|
||||
CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||
|
||||
// Individual permission.
|
||||
User.grantIapPermission("email@example.com", Optional.empty(), cloudTasksUtils, iamClient);
|
||||
User.grantIapPermission(
|
||||
"email@example.com", Optional.empty(), cloudTasksUtils, null, iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued();
|
||||
verify(iamClient).addBinding("email@example.com", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
|
||||
// Group membership.
|
||||
User.grantIapPermission(
|
||||
"email@example.com", Optional.of("console@example.com"), cloudTasksUtils, iamClient);
|
||||
"email@example.com", Optional.of("console@example.com"), cloudTasksUtils, null, iamClient);
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"console-user-group-update",
|
||||
new TaskMatcher()
|
||||
@@ -142,19 +176,49 @@ public class UserTest extends EntityTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRevokeIapPermission() {
|
||||
void testGrantIapPermissionSync() throws Exception {
|
||||
ServiceConnection connection = mock(ServiceConnection.class);
|
||||
IamClient iamClient = mock(IamClient.class);
|
||||
|
||||
// Individual permission.
|
||||
User.grantIapPermission("email@example.com", Optional.empty(), null, connection, iamClient);
|
||||
verifyNoInteractions(connection);
|
||||
verify(iamClient).addBinding("email@example.com", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
|
||||
// Group membership.
|
||||
User.grantIapPermission(
|
||||
"email@example.com", Optional.of("console@example.com"), null, connection, iamClient);
|
||||
verify(connection)
|
||||
.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
"email@example.com",
|
||||
"groupEmailAddress",
|
||||
"console@example.com",
|
||||
"groupUpdateMode",
|
||||
"ADD"),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
verifyNoMoreInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRevokeIapPermissionAsync() {
|
||||
CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
IamClient iamClient = mock(IamClient.class);
|
||||
CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||
|
||||
// Individual permission.
|
||||
User.revokeIapPermission("email@example.com", Optional.empty(), cloudTasksUtils, iamClient);
|
||||
User.revokeIapPermission(
|
||||
"email@example.com", Optional.empty(), cloudTasksUtils, null, iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued();
|
||||
verify(iamClient).removeBinding("email@example.com", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
|
||||
// Group membership.
|
||||
User.revokeIapPermission(
|
||||
"email@example.com", Optional.of("console@example.com"), cloudTasksUtils, iamClient);
|
||||
"email@example.com", Optional.of("console@example.com"), cloudTasksUtils, null, iamClient);
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"console-user-group-update",
|
||||
new TaskMatcher()
|
||||
@@ -166,4 +230,33 @@ public class UserTest extends EntityTestCase {
|
||||
.param("groupUpdateMode", "REMOVE"));
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRevokeIapPermissionSync() throws Exception {
|
||||
ServiceConnection connection = mock(ServiceConnection.class);
|
||||
IamClient iamClient = mock(IamClient.class);
|
||||
|
||||
// Individual permission.
|
||||
User.revokeIapPermission("email@example.com", Optional.empty(), null, connection, iamClient);
|
||||
verifyNoInteractions(connection);
|
||||
verify(iamClient).removeBinding("email@example.com", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
|
||||
// Group membership.
|
||||
User.revokeIapPermission(
|
||||
"email@example.com", Optional.of("console@example.com"), null, connection, iamClient);
|
||||
verify(connection)
|
||||
.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
"email@example.com",
|
||||
"groupEmailAddress",
|
||||
"console@example.com",
|
||||
"groupUpdateMode",
|
||||
"REMOVE"),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
verifyNoMoreInteractions(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ import google.registry.model.billing.BillingRecurrence;
|
||||
import google.registry.model.common.DnsRefreshRequest;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
@@ -1014,20 +1013,33 @@ public final class DatabaseHelper {
|
||||
return tm().transact(() -> tm().loadByEntity(resource));
|
||||
}
|
||||
|
||||
public static User loadExistingUser(String emailAddress) {
|
||||
return loadByKey(VKey.create(User.class, emailAddress));
|
||||
}
|
||||
|
||||
/** Persists an admin {@link User} with the given email address if it doesn't already exist. */
|
||||
public static User createAdminUser(String emailAddress) {
|
||||
Optional<User> existingUser = UserDao.loadUser(emailAddress);
|
||||
if (existingUser.isPresent()) {
|
||||
return existingUser.get();
|
||||
}
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setEmailAddress(emailAddress)
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).setIsAdmin(true).build())
|
||||
.build();
|
||||
tm().transact(() -> tm().put(user));
|
||||
return UserDao.loadUser(emailAddress).get();
|
||||
// Reload the user to pick up the update time
|
||||
return loadByEntity(
|
||||
tm().transact(
|
||||
() -> {
|
||||
VKey<User> key = VKey.create(User.class, emailAddress);
|
||||
Optional<User> existingUser = tm().loadByKeyIfPresent(key);
|
||||
if (existingUser.isPresent()) {
|
||||
return existingUser.get();
|
||||
}
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setEmailAddress(emailAddress)
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder()
|
||||
.setGlobalRole(GlobalRole.FTE)
|
||||
.setIsAdmin(true)
|
||||
.build())
|
||||
.build();
|
||||
tm().put(user);
|
||||
return user;
|
||||
}));
|
||||
}
|
||||
|
||||
/** Returns all the history entries that are parented off the given EppResource. */
|
||||
|
||||
@@ -16,22 +16,21 @@ package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.console.User.IAP_SECURED_WEB_APP_USER_ROLE;
|
||||
import static google.registry.testing.DatabaseHelper.loadExistingUser;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -40,13 +39,13 @@ import org.junit.jupiter.api.Test;
|
||||
public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
|
||||
private final IamClient iamClient = mock(IamClient.class);
|
||||
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
private final ServiceConnection connection = mock(ServiceConnection.class);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
command.iamClient = iamClient;
|
||||
command.maybeGroupEmailAddress = Optional.empty();
|
||||
command.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||
command.setConnection(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -59,7 +58,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
assertThat(onlyUser.getUserRoles().getRegistrarRoles()).isEmpty();
|
||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,16 +70,20 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
assertThat(onlyUser.getUserRoles().isAdmin()).isFalse();
|
||||
assertThat(onlyUser.getUserRoles().getGlobalRole()).isEqualTo(GlobalRole.NONE);
|
||||
assertThat(onlyUser.getUserRoles().getRegistrarRoles()).isEmpty();
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"console-user-group-update",
|
||||
new TaskMatcher()
|
||||
.method(HttpMethod.POST)
|
||||
.service("TOOLS")
|
||||
.path("/_dr/admin/updateUserGroup")
|
||||
.param("userEmailAddress", "user@example.test")
|
||||
.param("groupEmailAddress", "group@example.test")
|
||||
.param("groupUpdateMode", "ADD"));
|
||||
verify(connection)
|
||||
.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
"user@example.test",
|
||||
"groupEmailAddress",
|
||||
"group@example.test",
|
||||
"groupUpdateMode",
|
||||
"ADD"),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
verifyNoInteractions(iamClient);
|
||||
verifyNoMoreInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,27 +93,27 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
"user@example.test",
|
||||
"--registry_lock_email_address",
|
||||
"registrylockemail@otherexample.test");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getRegistryLockEmailAddress())
|
||||
assertThat(loadExistingUser("user@example.test").getRegistryLockEmailAddress())
|
||||
.hasValue("registrylockemail@otherexample.test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_admin() throws Exception {
|
||||
runCommandForced("--email", "user@example.test", "--admin", "true");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().isAdmin()).isTrue();
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().isAdmin()).isTrue();
|
||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_globalRole() throws Exception {
|
||||
runCommandForced("--email", "user@example.test", "--global_role", "FTE");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getGlobalRole())
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getGlobalRole())
|
||||
.isEqualTo(GlobalRole.FTE);
|
||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -120,7 +123,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
"user@example.test",
|
||||
"--registrar_roles",
|
||||
"TheRegistrar=ACCOUNT_MANAGER,NewRegistrar=PRIMARY_CONTACT");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getRegistrarRoles())
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getRegistrarRoles())
|
||||
.isEqualTo(
|
||||
ImmutableMap.of(
|
||||
"TheRegistrar",
|
||||
@@ -129,7 +132,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
RegistrarRole.PRIMARY_CONTACT));
|
||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,7 +147,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||
.hasMessageThat()
|
||||
.isEqualTo("A user with email user@example.test already exists");
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,11 +22,12 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.tools.server.UpdateUserGroupAction;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -35,43 +36,49 @@ import org.junit.jupiter.api.Test;
|
||||
public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
||||
|
||||
private final IamClient iamClient = mock(IamClient.class);
|
||||
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
private final ServiceConnection connection = mock(ServiceConnection.class);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
command.iamClient = iamClient;
|
||||
command.maybeGroupEmailAddress = Optional.empty();
|
||||
command.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||
command.setConnection(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_deletesUser() throws Exception {
|
||||
DatabaseHelper.createAdminUser("email@example.test");
|
||||
assertThat(UserDao.loadUser("email@example.test")).isPresent();
|
||||
VKey<User> key = VKey.create(User.class, "email@example.test");
|
||||
assertThat(DatabaseHelper.loadByKeyIfPresent(key)).isPresent();
|
||||
runCommandForced("--email", "email@example.test");
|
||||
assertThat(UserDao.loadUser("email@example.test")).isEmpty();
|
||||
assertThat(DatabaseHelper.loadByKeyIfPresent(key)).isEmpty();
|
||||
verify(iamClient).removeBinding("email@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||
verifyNoMoreInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_deletesUser_removeFromGroup() throws Exception {
|
||||
command.maybeGroupEmailAddress = Optional.of("group@example.test");
|
||||
DatabaseHelper.createAdminUser("email@example.test");
|
||||
assertThat(UserDao.loadUser("email@example.test")).isPresent();
|
||||
VKey<User> key = VKey.create(User.class, "email@example.test");
|
||||
assertThat(DatabaseHelper.loadByKeyIfPresent(key)).isPresent();
|
||||
runCommandForced("--email", "email@example.test");
|
||||
assertThat(UserDao.loadUser("email@example.test")).isEmpty();
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"console-user-group-update",
|
||||
new TaskMatcher()
|
||||
.method(HttpMethod.POST)
|
||||
.service("TOOLS")
|
||||
.path("/_dr/admin/updateUserGroup")
|
||||
.param("userEmailAddress", "email@example.test")
|
||||
.param("groupEmailAddress", "group@example.test")
|
||||
.param("groupUpdateMode", "REMOVE"));
|
||||
assertThat(DatabaseHelper.loadByKeyIfPresent(key)).isEmpty();
|
||||
verify(connection)
|
||||
.sendPostRequest(
|
||||
UpdateUserGroupAction.PATH,
|
||||
ImmutableMap.of(
|
||||
"userEmailAddress",
|
||||
"email@example.test",
|
||||
"groupEmailAddress",
|
||||
"group@example.test",
|
||||
"groupUpdateMode",
|
||||
"REMOVE"),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
verifyNoInteractions(iamClient);
|
||||
verifyNoMoreInteractions(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,6 +90,6 @@ public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Email does not correspond to a valid user");
|
||||
verifyNoInteractions(iamClient);
|
||||
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||
verifyNoInteractions(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -28,7 +29,7 @@ public class GetUserCommandTest extends CommandTestCase<GetUserCommand> {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
UserDao.saveUser(
|
||||
DatabaseHelper.putInDb(
|
||||
new User.Builder()
|
||||
.setEmailAddress("johndoe@theregistrar.com")
|
||||
.setUserRoles(
|
||||
@@ -36,8 +37,7 @@ public class GetUserCommandTest extends CommandTestCase<GetUserCommand> {
|
||||
.setRegistrarRoles(
|
||||
ImmutableMap.of("TheRegistrar", RegistrarRole.PRIMARY_CONTACT))
|
||||
.build())
|
||||
.build());
|
||||
UserDao.saveUser(
|
||||
.build(),
|
||||
new User.Builder()
|
||||
.setEmailAddress("fte@google.com")
|
||||
.setUserRoles(
|
||||
@@ -52,7 +52,6 @@ public class GetUserCommandTest extends CommandTestCase<GetUserCommand> {
|
||||
"""
|
||||
User: {
|
||||
emailAddress=fte@google.com
|
||||
id=2
|
||||
registryLockEmailAddress=null
|
||||
registryLockPasswordHash=null
|
||||
registryLockPasswordSalt=null
|
||||
@@ -75,7 +74,6 @@ public class GetUserCommandTest extends CommandTestCase<GetUserCommand> {
|
||||
"""
|
||||
User: {
|
||||
emailAddress=johndoe@theregistrar.com
|
||||
id=1
|
||||
registryLockEmailAddress=null
|
||||
registryLockPasswordHash=null
|
||||
registryLockPasswordSalt=null
|
||||
@@ -90,7 +88,6 @@ public class GetUserCommandTest extends CommandTestCase<GetUserCommand> {
|
||||
}
|
||||
User: {
|
||||
emailAddress=fte@google.com
|
||||
id=2
|
||||
registryLockEmailAddress=null
|
||||
registryLockPasswordHash=null
|
||||
registryLockPasswordSalt=null
|
||||
@@ -113,7 +110,6 @@ public class GetUserCommandTest extends CommandTestCase<GetUserCommand> {
|
||||
"""
|
||||
User: {
|
||||
emailAddress=johndoe@theregistrar.com
|
||||
id=1
|
||||
registryLockEmailAddress=null
|
||||
registryLockPasswordHash=null
|
||||
registryLockPasswordSalt=null
|
||||
|
||||
@@ -22,9 +22,11 @@ import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
||||
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
||||
import static google.registry.testing.CertificateSamples.SAMPLE_CERT_HASH;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadExistingUser;
|
||||
import static google.registry.testing.DatabaseHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.DatabaseHelper.putInDb;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
@@ -39,7 +41,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.tld.Tld;
|
||||
@@ -447,12 +448,11 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
||||
|
||||
@Test
|
||||
void testFailure_userExists() {
|
||||
User user =
|
||||
putInDb(
|
||||
new User.Builder()
|
||||
.setEmailAddress("contact@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||
.build();
|
||||
UserDao.saveUser(user);
|
||||
.build());
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
@@ -494,12 +494,11 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
||||
|
||||
@Test
|
||||
void testSuccess_userExists_replaceExisting() throws Exception {
|
||||
User user =
|
||||
putInDb(
|
||||
new User.Builder()
|
||||
.setEmailAddress("contact@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||
.build();
|
||||
UserDao.saveUser(user);
|
||||
.build());
|
||||
|
||||
runCommandForced(
|
||||
"--overwrite",
|
||||
@@ -520,7 +519,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
||||
verifyUser("blobio-5", "contact@email.com");
|
||||
|
||||
// verify that the role is completely replaced, e.g., the global role is gone.
|
||||
assertThat(UserDao.loadUser("contact@email.com").get().getUserRoles().getGlobalRole())
|
||||
assertThat(loadExistingUser("contact@email.com").getUserRoles().getGlobalRole())
|
||||
.isEqualTo(GlobalRole.NONE);
|
||||
|
||||
verifyIapPermission("contact@email.com");
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.loadExistingUser;
|
||||
import static google.registry.testing.DatabaseHelper.putInDb;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserDao;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -31,7 +32,7 @@ public class UpdateUserCommandTest extends CommandTestCase<UpdateUserCommand> {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
UserDao.saveUser(
|
||||
putInDb(
|
||||
new User.Builder()
|
||||
.setEmailAddress("user@example.test")
|
||||
.setUserRoles(new UserRoles.Builder().build())
|
||||
@@ -45,41 +46,39 @@ public class UpdateUserCommandTest extends CommandTestCase<UpdateUserCommand> {
|
||||
"user@example.test",
|
||||
"--registry_lock_email_address",
|
||||
"registrylockemail@otherexample.test");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getRegistryLockEmailAddress())
|
||||
assertThat(loadExistingUser("user@example.test").getRegistryLockEmailAddress())
|
||||
.hasValue("registrylockemail@otherexample.test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_removeRegistryLockEmail() throws Exception {
|
||||
UserDao.saveUser(
|
||||
UserDao.loadUser("user@example.test")
|
||||
.get()
|
||||
putInDb(
|
||||
loadExistingUser("user@example.test")
|
||||
.asBuilder()
|
||||
.setRegistryLockEmailAddress("registrylock@otherexample.test")
|
||||
.build());
|
||||
runCommandForced("--email", "user@example.test", "--registry_lock_email_address", "");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getRegistryLockEmailAddress()).isEmpty();
|
||||
assertThat(loadExistingUser("user@example.test").getRegistryLockEmailAddress()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_admin() throws Exception {
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().isAdmin()).isFalse();
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().isAdmin()).isFalse();
|
||||
runCommandForced("--email", "user@example.test", "--admin", "true");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().isAdmin()).isTrue();
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().isAdmin()).isTrue();
|
||||
runCommandForced("--email", "user@example.test", "--admin", "false");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().isAdmin()).isFalse();
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().isAdmin()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_registrarRoles() throws Exception {
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getRegistrarRoles())
|
||||
.isEmpty();
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getRegistrarRoles()).isEmpty();
|
||||
runCommandForced(
|
||||
"--email",
|
||||
"user@example.test",
|
||||
"--registrar_roles",
|
||||
"TheRegistrar=ACCOUNT_MANAGER,NewRegistrar=PRIMARY_CONTACT");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getRegistrarRoles())
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getRegistrarRoles())
|
||||
.isEqualTo(
|
||||
ImmutableMap.of(
|
||||
"TheRegistrar",
|
||||
@@ -87,16 +86,15 @@ public class UpdateUserCommandTest extends CommandTestCase<UpdateUserCommand> {
|
||||
"NewRegistrar",
|
||||
RegistrarRole.PRIMARY_CONTACT));
|
||||
runCommandForced("--email", "user@example.test", "--registrar_roles", "");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getRegistrarRoles())
|
||||
.isEmpty();
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getRegistrarRoles()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_globalRole() throws Exception {
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getGlobalRole())
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getGlobalRole())
|
||||
.isEqualTo(GlobalRole.NONE);
|
||||
runCommandForced("--email", "user@example.test", "--global_role", "FTE");
|
||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().getGlobalRole())
|
||||
assertThat(loadExistingUser("user@example.test").getUserRoles().getGlobalRole())
|
||||
.isEqualTo(GlobalRole.FTE);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public class ConsoleRegistryLockVerifyActionTest {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
assertThat(response.getPayload())
|
||||
.isEqualTo(
|
||||
"{\"action\":\"unlocked\",\"domainName\":\"example.test\",\"registrarId\":\"TheRegistrar\"}");
|
||||
"{\"action\":\"locked\",\"domainName\":\"example.test\",\"registrarId\":\"TheRegistrar\"}");
|
||||
assertThat(loadByEntity(defaultDomain).getStatusValues())
|
||||
.containsAtLeastElementsIn(REGISTRY_LOCK_STATUSES);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public class ConsoleRegistryLockVerifyActionTest {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
assertThat(response.getPayload())
|
||||
.isEqualTo(
|
||||
"{\"action\":\"unlocked\",\"domainName\":\"example.test\",\"registrarId\":\"TheRegistrar\"}");
|
||||
"{\"action\":\"locked\",\"domainName\":\"example.test\",\"registrarId\":\"TheRegistrar\"}");
|
||||
assertThat(loadByEntity(defaultDomain).getStatusValues())
|
||||
.containsAtLeastElementsIn(REGISTRY_LOCK_STATUSES);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.ui.server.console.settings;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.ADMIN;
|
||||
import static google.registry.model.registrar.RegistrarPocBase.Type.WHOIS;
|
||||
import static google.registry.testing.DatabaseHelper.createAdminUser;
|
||||
import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
import static google.registry.testing.DatabaseHelper.loadAllOf;
|
||||
@@ -67,7 +66,7 @@ class ContactActionTest {
|
||||
+ "\"emailAddress\":\"test.registrar1@example.com\","
|
||||
+ "\"registrarId\":\"registrarId\","
|
||||
+ "\"phoneNumber\":\"+1.9999999999\",\"faxNumber\":\"+1.9999999991\","
|
||||
+ "\"types\":[\"WHOIS\",\"ADMIN\"],\"visibleInWhoisAsAdmin\":true,"
|
||||
+ "\"types\":[\"ADMIN\"],\"visibleInWhoisAsAdmin\":true,"
|
||||
+ "\"visibleInWhoisAsTech\":false,\"visibleInDomainWhoisAsAbuse\":false}";
|
||||
|
||||
private static String jsonRegistrar2 =
|
||||
@@ -75,7 +74,7 @@ class ContactActionTest {
|
||||
+ "\"emailAddress\":\"test.registrar2@example.com\","
|
||||
+ "\"registrarId\":\"registrarId\","
|
||||
+ "\"phoneNumber\":\"+1.1234567890\",\"faxNumber\":\"+1.1234567891\","
|
||||
+ "\"types\":[\"WHOIS\",\"ADMIN\"],\"visibleInWhoisAsAdmin\":true,"
|
||||
+ "\"types\":[\"ADMIN\"],\"visibleInWhoisAsAdmin\":true,"
|
||||
+ "\"visibleInWhoisAsTech\":false,\"visibleInDomainWhoisAsAbuse\":false}";
|
||||
|
||||
private Registrar testRegistrar;
|
||||
@@ -97,7 +96,7 @@ class ContactActionTest {
|
||||
.setEmailAddress("test.registrar1@example.com")
|
||||
.setPhoneNumber("+1.9999999999")
|
||||
.setFaxNumber("+1.9999999991")
|
||||
.setTypes(ImmutableSet.of(WHOIS, ADMIN))
|
||||
.setTypes(ImmutableSet.of(ADMIN))
|
||||
.setVisibleInWhoisAsAdmin(true)
|
||||
.setVisibleInWhoisAsTech(false)
|
||||
.setVisibleInDomainWhoisAsAbuse(false)
|
||||
@@ -218,22 +217,22 @@ class ContactActionTest {
|
||||
+ " {name=Test Registrar 1,"
|
||||
+ " emailAddress=test.registrar1@example.com, registrarId=registrarId,"
|
||||
+ " registryLockEmailAddress=null, phoneNumber=+1.9999999999,"
|
||||
+ " faxNumber=+1.9999999991, types=[ADMIN, WHOIS],"
|
||||
+ " faxNumber=+1.9999999991, types=[ADMIN],"
|
||||
+ " visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false,"
|
||||
+ " visibleInDomainWhoisAsAbuse=false,"
|
||||
+ " allowedToSetRegistryLockPassword=false}\n"
|
||||
+ " REMOVED:\n"
|
||||
+ " {name=Test Registrar 1, emailAddress=incorrect@email.com,"
|
||||
+ " registrarId=registrarId, registryLockEmailAddress=null,"
|
||||
+ " phoneNumber=+1.9999999999, faxNumber=+1.9999999991, types=[WHOIS,"
|
||||
+ " ADMIN], visibleInWhoisAsAdmin=true,"
|
||||
+ " phoneNumber=+1.9999999999, faxNumber=+1.9999999991, types=[ADMIN],"
|
||||
+ " visibleInWhoisAsAdmin=true,"
|
||||
+ " visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false,"
|
||||
+ " allowedToSetRegistryLockPassword=false}\n"
|
||||
+ " FINAL CONTENTS:\n"
|
||||
+ " {name=Test Registrar 1,"
|
||||
+ " emailAddress=test.registrar1@example.com, registrarId=registrarId,"
|
||||
+ " registryLockEmailAddress=null, phoneNumber=+1.9999999999,"
|
||||
+ " faxNumber=+1.9999999991, types=[ADMIN, WHOIS],"
|
||||
+ " faxNumber=+1.9999999991, types=[ADMIN],"
|
||||
+ " visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false,"
|
||||
+ " visibleInDomainWhoisAsAbuse=false,"
|
||||
+ " allowedToSetRegistryLockPassword=false}\n")
|
||||
|
||||
@@ -104,6 +104,8 @@ public class WhoisRegistrarFieldsActionTest {
|
||||
ImmutableMap.of(
|
||||
"whoisServer",
|
||||
"whois.nic.google",
|
||||
"icannReferralEmail",
|
||||
"lol@sloth.test",
|
||||
"phoneNumber",
|
||||
"+1.4155552671",
|
||||
"faxNumber",
|
||||
|
||||
@@ -29,6 +29,8 @@ import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STAT
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.common.FeatureFlag;
|
||||
import google.registry.model.console.RegistrarRole;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.RegistryLock;
|
||||
@@ -110,15 +112,6 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
|
||||
driver.diffPage("page");
|
||||
}
|
||||
|
||||
/** Admins shouldn't have the "add" button */
|
||||
@RetryingTest(3)
|
||||
void settingsContact_asAdmin() throws Throwable {
|
||||
server.setIsAdmin(true);
|
||||
driver.get(server.getUrl("/registrar?clientId=NewRegistrar#contact-settings"));
|
||||
driver.waitForDisplayedElement(By.tagName("h1"));
|
||||
driver.diffPage("page");
|
||||
}
|
||||
|
||||
@RetryingTest(3)
|
||||
void settingsContactItem() throws Throwable {
|
||||
driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com"));
|
||||
@@ -518,6 +511,18 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
|
||||
driver.diffPage("page");
|
||||
}
|
||||
|
||||
@RetryingTest(3)
|
||||
void deprecationWarning_active() throws Throwable {
|
||||
persistResource(
|
||||
new FeatureFlag.Builder()
|
||||
.setFeatureName(FeatureFlag.FeatureName.NEW_CONSOLE)
|
||||
.setStatusMap(ImmutableSortedMap.of(START_OF_TIME, FeatureFlag.FeatureStatus.ACTIVE))
|
||||
.build());
|
||||
driver.get(server.getUrl("/registrar"));
|
||||
driver.waitForDisplayedElement(By.tagName("h1"));
|
||||
driver.diffPage("page");
|
||||
}
|
||||
|
||||
private static void createDomainAndSaveLock() {
|
||||
createTld("tld");
|
||||
Domain domain = persistActiveDomain("example.tld");
|
||||
|
||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
@@ -257,15 +257,15 @@ td.section {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="property_name">generated by</td>
|
||||
<td class="property_value">SchemaCrawler 16.21.2</td>
|
||||
<td class="property_value">SchemaCrawler 16.21.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="property_name">generated on</td>
|
||||
<td class="property_value">2024-06-20 20:07:00</td>
|
||||
<td class="property_value">2024-08-01 19:19:23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="property_name">last flyway file</td>
|
||||
<td id="lastFlywayFile" class="property_value">V173__create_feature_flag_table.sql</td>
|
||||
<td id="lastFlywayFile" class="property_value">V176__drop_login_email_address_column_from_registrar_poc.sql</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -278,9 +278,9 @@ td.section {
|
||||
</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-9412 4738,-9412 4738,4 -4,4" />
|
||||
<text text-anchor="start" x="4494" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated by</text>
|
||||
<text text-anchor="start" x="4577" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 16.21.2</text>
|
||||
<text text-anchor="start" x="4577" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 16.21.4</text>
|
||||
<text text-anchor="start" x="4493" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated on</text>
|
||||
<text text-anchor="start" x="4577" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">2024-06-20 20:07:00</text>
|
||||
<text text-anchor="start" x="4577" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">2024-08-01 19:19:23</text>
|
||||
<polygon fill="none" stroke="#888888" points="4490,-4 4490,-44 4726,-44 4726,-4 4490,-4" /> <!-- allocationtoken_a08ccbef -->
|
||||
<g id="node1" class="node">
|
||||
<title>
|
||||
@@ -2071,12 +2071,12 @@ td.section {
|
||||
<text text-anchor="start" x="713" y="-504.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">public."User"</text>
|
||||
<polygon fill="#e9c2f2" stroke="transparent" points="901,-497.5 901,-516.5 1011,-516.5 1011,-497.5 901,-497.5" />
|
||||
<text text-anchor="start" x="972" y="-503.3" font-family="Helvetica,sans-Serif" font-size="14.00">[table]</text>
|
||||
<text text-anchor="start" x="713" y="-485.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">id</text>
|
||||
<text text-anchor="start" x="713" y="-484.3" font-family="Helvetica,sans-Serif" font-size="14.00">id</text>
|
||||
<text text-anchor="start" x="895" y="-484.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="903" y="-484.3" font-family="Helvetica,sans-Serif" font-size="14.00">bigserial not null</text>
|
||||
<text text-anchor="start" x="903" y="-484.3" font-family="Helvetica,sans-Serif" font-size="14.00">bigserial</text>
|
||||
<text text-anchor="start" x="895" y="-465.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="903" y="-465.3" font-family="Helvetica,sans-Serif" font-size="14.00">auto-incremented</text>
|
||||
<text text-anchor="start" x="713" y="-446.3" font-family="Helvetica,sans-Serif" font-size="14.00">email_address</text>
|
||||
<text text-anchor="start" x="713" y="-447.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">email_address</text>
|
||||
<text text-anchor="start" x="895" y="-446.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="903" y="-446.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
<text text-anchor="start" x="713" y="-427.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_password_hash</text>
|
||||
@@ -3425,61 +3425,58 @@ td.section {
|
||||
<title>
|
||||
registrarpoc_ab47054d
|
||||
</title>
|
||||
<polygon fill="#e9c2f2" stroke="transparent" points="697,-2093.5 697,-2112.5 948,-2112.5 948,-2093.5 697,-2093.5" />
|
||||
<text text-anchor="start" x="699" y="-2100.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">public."RegistrarPoc"</text>
|
||||
<polygon fill="#e9c2f2" stroke="transparent" points="948,-2093.5 948,-2112.5 1025,-2112.5 1025,-2093.5 948,-2093.5" />
|
||||
<text text-anchor="start" x="986" y="-2099.3" font-family="Helvetica,sans-Serif" font-size="14.00">[table]</text>
|
||||
<text text-anchor="start" x="699" y="-2081.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">email_address</text>
|
||||
<text text-anchor="start" x="942" y="-2080.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2080.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
<text text-anchor="start" x="699" y="-2061.3" font-family="Helvetica,sans-Serif" font-size="14.00">allowed_to_set_registry_lock_password</text>
|
||||
<text text-anchor="start" x="942" y="-2061.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2061.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-2042.3" font-family="Helvetica,sans-Serif" font-size="14.00">fax_number</text>
|
||||
<text text-anchor="start" x="942" y="-2042.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2042.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-2023.3" font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
|
||||
<text text-anchor="start" x="942" y="-2023.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2023.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-2004.3" font-family="Helvetica,sans-Serif" font-size="14.00">phone_number</text>
|
||||
<text text-anchor="start" x="942" y="-2004.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2004.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1985.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_password_hash</text>
|
||||
<text text-anchor="start" x="942" y="-1985.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1985.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1966.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_password_salt</text>
|
||||
<text text-anchor="start" x="942" y="-1966.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1966.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1947.3" font-family="Helvetica,sans-Serif" font-size="14.00">types</text>
|
||||
<text text-anchor="start" x="942" y="-1947.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1947.3" font-family="Helvetica,sans-Serif" font-size="14.00">_text</text>
|
||||
<text text-anchor="start" x="699" y="-1928.3" font-family="Helvetica,sans-Serif" font-size="14.00">visible_in_domain_whois_as_abuse</text>
|
||||
<text text-anchor="start" x="942" y="-1928.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1928.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-1909.3" font-family="Helvetica,sans-Serif" font-size="14.00">visible_in_whois_as_admin</text>
|
||||
<text text-anchor="start" x="942" y="-1909.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1909.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-1890.3" font-family="Helvetica,sans-Serif" font-size="14.00">visible_in_whois_as_tech</text>
|
||||
<text text-anchor="start" x="942" y="-1890.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1890.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-1871.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_email_address</text>
|
||||
<text text-anchor="start" x="942" y="-1871.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1871.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1853.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">registrar_id</text>
|
||||
<text text-anchor="start" x="942" y="-1852.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1852.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
<text text-anchor="start" x="699" y="-1833.3" font-family="Helvetica,sans-Serif" font-size="14.00">login_email_address</text>
|
||||
<text text-anchor="start" x="942" y="-1833.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1833.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<polygon fill="none" stroke="#888888" points="696,-1827 696,-2114 1026,-2114 1026,-1827 696,-1827" />
|
||||
<polygon fill="#e9c2f2" stroke="transparent" points="697,-2094.5 697,-2113.5 948,-2113.5 948,-2094.5 697,-2094.5" />
|
||||
<text text-anchor="start" x="699" y="-2101.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">public."RegistrarPoc"</text>
|
||||
<polygon fill="#e9c2f2" stroke="transparent" points="948,-2094.5 948,-2113.5 1025,-2113.5 1025,-2094.5 948,-2094.5" />
|
||||
<text text-anchor="start" x="986" y="-2100.3" font-family="Helvetica,sans-Serif" font-size="14.00">[table]</text>
|
||||
<text text-anchor="start" x="699" y="-2082.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">email_address</text>
|
||||
<text text-anchor="start" x="942" y="-2081.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2081.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
<text text-anchor="start" x="699" y="-2062.3" font-family="Helvetica,sans-Serif" font-size="14.00">allowed_to_set_registry_lock_password</text>
|
||||
<text text-anchor="start" x="942" y="-2062.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2062.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-2043.3" font-family="Helvetica,sans-Serif" font-size="14.00">fax_number</text>
|
||||
<text text-anchor="start" x="942" y="-2043.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2043.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-2024.3" font-family="Helvetica,sans-Serif" font-size="14.00">name</text>
|
||||
<text text-anchor="start" x="942" y="-2024.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2024.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-2005.3" font-family="Helvetica,sans-Serif" font-size="14.00">phone_number</text>
|
||||
<text text-anchor="start" x="942" y="-2005.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-2005.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1986.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_password_hash</text>
|
||||
<text text-anchor="start" x="942" y="-1986.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1986.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1967.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_password_salt</text>
|
||||
<text text-anchor="start" x="942" y="-1967.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1967.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1948.3" font-family="Helvetica,sans-Serif" font-size="14.00">types</text>
|
||||
<text text-anchor="start" x="942" y="-1948.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1948.3" font-family="Helvetica,sans-Serif" font-size="14.00">_text</text>
|
||||
<text text-anchor="start" x="699" y="-1929.3" font-family="Helvetica,sans-Serif" font-size="14.00">visible_in_domain_whois_as_abuse</text>
|
||||
<text text-anchor="start" x="942" y="-1929.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1929.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-1910.3" font-family="Helvetica,sans-Serif" font-size="14.00">visible_in_whois_as_admin</text>
|
||||
<text text-anchor="start" x="942" y="-1910.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1910.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-1891.3" font-family="Helvetica,sans-Serif" font-size="14.00">visible_in_whois_as_tech</text>
|
||||
<text text-anchor="start" x="942" y="-1891.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1891.3" font-family="Helvetica,sans-Serif" font-size="14.00">bool not null</text>
|
||||
<text text-anchor="start" x="699" y="-1872.3" font-family="Helvetica,sans-Serif" font-size="14.00">registry_lock_email_address</text>
|
||||
<text text-anchor="start" x="942" y="-1872.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1872.3" font-family="Helvetica,sans-Serif" font-size="14.00">text</text>
|
||||
<text text-anchor="start" x="699" y="-1854.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">registrar_id</text>
|
||||
<text text-anchor="start" x="942" y="-1853.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="950" y="-1853.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
<polygon fill="none" stroke="#888888" points="696,-1846.5 696,-2114.5 1026,-2114.5 1026,-1846.5 696,-1846.5" />
|
||||
</g> <!-- registrarpoc_ab47054d->registrar_6e1503e3 -->
|
||||
<g id="edge76" class="edge">
|
||||
<title>
|
||||
registrarpoc_ab47054d:w->registrar_6e1503e3:e
|
||||
</title>
|
||||
<path fill="none" stroke="black" d="M677.75,-1856.09C540.68,-1865.23 521.94,-1979.48 470,-2117.5 454.68,-2158.21 486.76,-5152.06 448.04,-5342.06" />
|
||||
<polygon fill="black" stroke="black" points="686.01,-1855.82 696.15,-1860 691,-1855.66 696,-1855.5 696,-1855.5 696,-1855.5 691,-1855.66 695.85,-1851 686.01,-1855.82 686.01,-1855.82" />
|
||||
<ellipse fill="none" stroke="black" cx="682.01" cy="-1855.95" rx="4" ry="4" />
|
||||
<path fill="none" stroke="black" d="M677.79,-1857.09C540.99,-1866.18 521.95,-1979.83 470,-2117.5 454.64,-2158.19 486.76,-5152.06 448.04,-5342.06" />
|
||||
<polygon fill="black" stroke="black" points="686.01,-1856.82 696.14,-1861 691,-1856.66 696,-1856.5 696,-1856.5 696,-1856.5 691,-1856.66 695.86,-1852 686.01,-1856.82 686.01,-1856.82" />
|
||||
<ellipse fill="none" stroke="black" cx="682.01" cy="-1856.95" rx="4" ry="4" />
|
||||
<polygon fill="black" stroke="black" points="448.99,-5352.55 439.8,-5348.61 440.58,-5346.78 449.78,-5350.71 448.99,-5352.55" />
|
||||
<polyline fill="none" stroke="black" points="444,-5351.5 445.97,-5346.9 " />
|
||||
<polygon fill="black" stroke="black" points="450.96,-5347.95 441.76,-5344.02 442.55,-5342.18 451.74,-5346.11 450.96,-5347.95" />
|
||||
@@ -3659,14 +3656,14 @@ td.section {
|
||||
<title>
|
||||
registrarupdatehistory_8a38bed4:w->registrar_6e1503e3:e
|
||||
</title>
|
||||
<path fill="none" stroke="black" d="M1332.75,-685.31C1306.86,-790.03 1336.07,-1380.67 1316,-1412.5 1089.82,-1771.16 691.21,-1491.76 470,-1853.5 445.42,-1893.69 489.75,-5145.35 448.15,-5342.19" />
|
||||
<polygon fill="black" stroke="black" points="1336.95,-678.13 1345.88,-671.77 1339.48,-673.82 1342,-669.5 1342,-669.5 1342,-669.5 1339.48,-673.82 1338.12,-667.23 1336.95,-678.13 1336.95,-678.13" />
|
||||
<ellipse fill="none" stroke="black" cx="1334.93" cy="-681.58" rx="4" ry="4" />
|
||||
<path fill="none" stroke="black" d="M1332.73,-685.18C1306.41,-790.38 1336.49,-1390.29 1316,-1422.5 1089.39,-1778.71 691.77,-1495.25 470,-1854.5 445.26,-1894.58 489.73,-5145.4 448.15,-5342.19" />
|
||||
<polygon fill="black" stroke="black" points="1336.91,-678.11 1345.87,-671.79 1339.45,-673.8 1342,-669.5 1342,-669.5 1342,-669.5 1339.45,-673.8 1338.13,-667.21 1336.91,-678.11 1336.91,-678.11" />
|
||||
<ellipse fill="none" stroke="black" cx="1334.87" cy="-681.55" rx="4" ry="4" />
|
||||
<polygon fill="black" stroke="black" points="448.97,-5352.62 439.84,-5348.55 440.65,-5346.72 449.79,-5350.8 448.97,-5352.62" />
|
||||
<polyline fill="none" stroke="black" points="444,-5351.5 446.04,-5346.93 " />
|
||||
<polygon fill="black" stroke="black" points="451.01,-5348.06 441.88,-5343.98 442.69,-5342.16 451.82,-5346.23 451.01,-5348.06" />
|
||||
<polyline fill="none" stroke="black" points="446.04,-5346.93 448.07,-5342.37 " />
|
||||
<text text-anchor="start" x="760" y="-1674.3" font-family="Helvetica,sans-Serif" font-size="14.00">fkregistrarupdatehistoryregistrarid</text>
|
||||
<text text-anchor="start" x="760" y="-1680.3" font-family="Helvetica,sans-Serif" font-size="14.00">fkregistrarupdatehistoryregistrarid</text>
|
||||
</g> <!-- registrarupdatehistory_8a38bed4->user_f2216f01 -->
|
||||
<g id="edge87" class="edge">
|
||||
<title>
|
||||
@@ -3758,26 +3755,26 @@ td.section {
|
||||
<title>
|
||||
registrarpocupdatehistory_31e5d9aa:w->registrarpoc_ab47054d:e
|
||||
</title>
|
||||
<path fill="none" stroke="black" d="M1352.71,-1972C1210.95,-1979.97 1182.3,-2079.86 1036.26,-2084.34" />
|
||||
<path fill="none" stroke="black" d="M1352.7,-1972.01C1210.84,-1980.05 1182.43,-2080.82 1036.26,-2085.34" />
|
||||
<polygon fill="black" stroke="black" points="1361,-1971.78 1371.12,-1976 1366,-1971.64 1371,-1971.5 1371,-1971.5 1371,-1971.5 1366,-1971.64 1370.88,-1967 1361,-1971.78 1361,-1971.78" />
|
||||
<ellipse fill="none" stroke="black" cx="1357.01" cy="-1971.89" rx="4" ry="4" />
|
||||
<polygon fill="black" stroke="black" points="1027.08,-2089.48 1026.92,-2079.49 1028.92,-2079.46 1029.08,-2089.45 1027.08,-2089.48" />
|
||||
<polyline fill="none" stroke="black" points="1026,-2084.5 1031,-2084.42 " />
|
||||
<polygon fill="black" stroke="black" points="1032.08,-2089.41 1031.92,-2079.41 1033.92,-2079.38 1034.08,-2089.38 1032.08,-2089.41" />
|
||||
<polyline fill="none" stroke="black" points="1031,-2084.42 1036,-2084.35 " />
|
||||
<text text-anchor="start" x="1062" y="-2087.3" font-family="Helvetica,sans-Serif" font-size="14.00">fkregistrarpocupdatehistoryemailaddress</text>
|
||||
<polygon fill="black" stroke="black" points="1027.08,-2090.48 1026.92,-2080.49 1028.92,-2080.45 1029.08,-2090.45 1027.08,-2090.48" />
|
||||
<polyline fill="none" stroke="black" points="1026,-2085.5 1031,-2085.42 " />
|
||||
<polygon fill="black" stroke="black" points="1032.08,-2090.41 1031.92,-2080.41 1033.92,-2080.38 1034.08,-2090.38 1032.08,-2090.41" />
|
||||
<polyline fill="none" stroke="black" points="1031,-2085.42 1036,-2085.35 " />
|
||||
<text text-anchor="start" x="1062" y="-2088.3" font-family="Helvetica,sans-Serif" font-size="14.00">fkregistrarpocupdatehistoryemailaddress</text>
|
||||
</g> <!-- registrarpocupdatehistory_31e5d9aa->registrarpoc_ab47054d -->
|
||||
<g id="edge79" class="edge">
|
||||
<title>
|
||||
registrarpocupdatehistory_31e5d9aa:w->registrarpoc_ab47054d:e
|
||||
</title>
|
||||
<path fill="none" stroke="black" d="M1352.93,-1952.07C1212.68,-1945.23 1180.48,-1859.48 1036.13,-1855.63" />
|
||||
<path fill="none" stroke="black" d="M1352.94,-1952.07C1212.77,-1945.3 1180.37,-1860.44 1036.12,-1856.63" />
|
||||
<polygon fill="black" stroke="black" points="1361,-1952.26 1370.89,-1957 1366,-1952.38 1371,-1952.5 1371,-1952.5 1371,-1952.5 1366,-1952.38 1371.11,-1948 1361,-1952.26 1361,-1952.26" />
|
||||
<ellipse fill="none" stroke="black" cx="1357" cy="-1952.17" rx="4" ry="4" />
|
||||
<polygon fill="black" stroke="black" points="1026.93,-1860.51 1027.07,-1850.51 1029.07,-1850.54 1028.93,-1860.54 1026.93,-1860.51" />
|
||||
<polyline fill="none" stroke="black" points="1026,-1855.5 1031,-1855.57 " />
|
||||
<polygon fill="black" stroke="black" points="1031.93,-1860.58 1032.07,-1850.58 1034.07,-1850.61 1033.93,-1860.61 1031.93,-1860.58" />
|
||||
<polyline fill="none" stroke="black" points="1031,-1855.57 1036,-1855.63 " />
|
||||
<polygon fill="black" stroke="black" points="1026.93,-1861.51 1027.07,-1851.51 1029.07,-1851.54 1028.93,-1861.54 1026.93,-1861.51" />
|
||||
<polyline fill="none" stroke="black" points="1026,-1856.5 1031,-1856.57 " />
|
||||
<polygon fill="black" stroke="black" points="1031.93,-1861.58 1032.06,-1851.58 1034.06,-1851.6 1033.93,-1861.6 1031.93,-1861.58" />
|
||||
<polyline fill="none" stroke="black" points="1031,-1856.57 1036,-1856.63 " />
|
||||
<text text-anchor="start" x="1062" y="-1951.3" font-family="Helvetica,sans-Serif" font-size="14.00">fkregistrarpocupdatehistoryemailaddress</text>
|
||||
</g> <!-- registrarpocupdatehistory_31e5d9aa->user_f2216f01 -->
|
||||
<g id="edge86" class="edge">
|
||||
@@ -4065,7 +4062,7 @@ td.section {
|
||||
<text text-anchor="start" x="1594" y="-485.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
<text text-anchor="start" x="1404" y="-466.3" font-family="Helvetica,sans-Serif" font-size="14.00">user_id</text>
|
||||
<text text-anchor="start" x="1586" y="-466.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="1594" y="-466.3" font-family="Helvetica,sans-Serif" font-size="14.00">int8 not null</text>
|
||||
<text text-anchor="start" x="1594" y="-466.3" font-family="Helvetica,sans-Serif" font-size="14.00">int8</text>
|
||||
<text text-anchor="start" x="1404" y="-447.3" font-family="Helvetica,sans-Serif" font-size="14.00">email_address</text>
|
||||
<text text-anchor="start" x="1586" y="-447.3" font-family="Helvetica,sans-Serif" font-size="14.00"> </text>
|
||||
<text text-anchor="start" x="1594" y="-447.3" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text>
|
||||
@@ -11362,11 +11359,6 @@ td.section {
|
||||
<td class="minwidth"><b><i>registrar_id</i></b></td>
|
||||
<td class="minwidth">text not null</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">login_email_address</td>
|
||||
<td class="minwidth">text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
@@ -11434,18 +11426,6 @@ td.section {
|
||||
<tr>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="name">registrarpoc_login_email_idx</td>
|
||||
<td class="description right">[non-unique index]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">login_email_address</td>
|
||||
<td class="minwidth">ascending</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="name">"RegistrarPoc_pkey"</td>
|
||||
<td class="description right">[unique index]</td>
|
||||
@@ -13113,8 +13093,8 @@ td.section {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth"><b><i>id</i></b></td>
|
||||
<td class="minwidth">bigserial not null</td>
|
||||
<td class="minwidth">id</td>
|
||||
<td class="minwidth">bigserial</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
@@ -13123,7 +13103,7 @@ td.section {
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">email_address</td>
|
||||
<td class="minwidth"><b><i>email_address</i></b></td>
|
||||
<td class="minwidth">text not null</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -13176,7 +13156,7 @@ td.section {
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">id</td>
|
||||
<td class="minwidth">email_address</td>
|
||||
<td class="minwidth"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -13260,7 +13240,7 @@ td.section {
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">id</td>
|
||||
<td class="minwidth">email_address</td>
|
||||
<td class="minwidth">ascending</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -13275,18 +13255,6 @@ td.section {
|
||||
<td class="minwidth">email_address</td>
|
||||
<td class="minwidth">ascending</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="name">user_email_address_idx</td>
|
||||
<td class="description right">[non-unique index]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">email_address</td>
|
||||
<td class="minwidth">ascending</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p> </p>
|
||||
@@ -13328,7 +13296,7 @@ td.section {
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
<td class="minwidth">user_id</td>
|
||||
<td class="minwidth">int8 not null</td>
|
||||
<td class="minwidth">int8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"></td>
|
||||
|
||||
@@ -171,3 +171,6 @@ V170__user_update_registry_lock_email.sql
|
||||
V171__drop_create_billing_cost_columns_from_tld.sql
|
||||
V172__allocation_token_renewal_price.sql
|
||||
V173__create_feature_flag_table.sql
|
||||
V174__user_pkey.sql
|
||||
V175__user_update_history_id.sql
|
||||
V176__drop_login_email_address_column_from_registrar_poc.sql
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
--
|
||||
-- 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.
|
||||
|
||||
ALTER TABLE "User" DROP CONSTRAINT "User_pkey";
|
||||
ALTER TABLE "User" ADD CONSTRAINT "User_pkey" PRIMARY KEY (email_address);
|
||||
ALTER TABLE "User" ALTER COLUMN id DROP NOT NULL;
|
||||
DROP INDEX user_email_address_idx;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
--
|
||||
-- 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.
|
||||
|
||||
ALTER TABLE "UserUpdateHistory" ALTER COLUMN user_id DROP NOT NULL;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
--
|
||||
-- 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.
|
||||
|
||||
alter table "RegistrarPoc" drop column login_email_address;
|
||||
@@ -885,16 +885,15 @@
|
||||
);
|
||||
|
||||
create table "User" (
|
||||
id bigserial not null,
|
||||
email_address text not null,
|
||||
update_timestamp timestamptz,
|
||||
email_address text not null,
|
||||
registry_lock_email_address text,
|
||||
registry_lock_password_hash text,
|
||||
registry_lock_password_salt text,
|
||||
global_role text not null,
|
||||
is_admin boolean not null,
|
||||
registrar_roles hstore,
|
||||
primary key (id)
|
||||
primary key (email_address)
|
||||
);
|
||||
|
||||
create table "UserUpdateHistory" (
|
||||
@@ -904,7 +903,6 @@
|
||||
history_request_body text,
|
||||
history_type text not null,
|
||||
history_url text not null,
|
||||
user_id int8 not null,
|
||||
email_address text not null,
|
||||
registry_lock_email_address text,
|
||||
registry_lock_password_hash text,
|
||||
@@ -1016,17 +1014,13 @@ create index reservedlist_name_idx on "ReservedList" (name);
|
||||
create index spec11threatmatch_registrar_id_idx on "Spec11ThreatMatch" (registrar_id);
|
||||
create index spec11threatmatch_tld_idx on "Spec11ThreatMatch" (tld);
|
||||
create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date);
|
||||
create index user_email_address_idx on "User" (email_address);
|
||||
|
||||
alter table if exists "User"
|
||||
add constraint UK_seshmd8qn3lcffsjw5j8wnbnd unique (email_address);
|
||||
create index IDXbjacjlm8ianc4kxxvamnu94k5 on "UserUpdateHistory" (history_acting_user);
|
||||
create index IDX5yqacw829y5bm6f7eajsq1cts on "UserUpdateHistory" (email_address);
|
||||
|
||||
alter table if exists "ConsoleEppActionHistory"
|
||||
add constraint FKb686b9os2nsjpv930npa4r3b4
|
||||
foreign key (history_acting_user)
|
||||
references "User" (email_address);
|
||||
references "User";
|
||||
|
||||
alter table if exists "DelegationSignerData"
|
||||
add constraint FKtr24j9v14ph2mfuw2gsmt12kq
|
||||
@@ -1066,12 +1060,12 @@ create index IDX5yqacw829y5bm6f7eajsq1cts on "UserUpdateHistory" (email_address)
|
||||
alter table if exists "RegistrarPocUpdateHistory"
|
||||
add constraint FKftpbwctxtkc1i0njc0tdcaa2g
|
||||
foreign key (history_acting_user)
|
||||
references "User" (email_address);
|
||||
references "User";
|
||||
|
||||
alter table if exists "RegistrarUpdateHistory"
|
||||
add constraint FKsr7w342s7x5s5jvdti2axqeq8
|
||||
foreign key (history_acting_user)
|
||||
references "User" (email_address);
|
||||
references "User";
|
||||
|
||||
alter table if exists "RegistryLock"
|
||||
add constraint FK2lhcwpxlnqijr96irylrh1707
|
||||
@@ -1086,4 +1080,4 @@ create index IDX5yqacw829y5bm6f7eajsq1cts on "UserUpdateHistory" (email_address)
|
||||
alter table if exists "UserUpdateHistory"
|
||||
add constraint FK1s7bopbl3pwrhv3jkkofnv3o0
|
||||
foreign key (history_acting_user)
|
||||
references "User" (email_address);
|
||||
references "User";
|
||||
|
||||
@@ -986,8 +986,7 @@ CREATE TABLE public."RegistrarPoc" (
|
||||
visible_in_whois_as_admin boolean NOT NULL,
|
||||
visible_in_whois_as_tech boolean NOT NULL,
|
||||
registry_lock_email_address text,
|
||||
registrar_id text NOT NULL,
|
||||
login_email_address text
|
||||
registrar_id text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
@@ -1317,7 +1316,7 @@ CREATE TABLE public."TmchCrl" (
|
||||
--
|
||||
|
||||
CREATE TABLE public."User" (
|
||||
id bigint NOT NULL,
|
||||
id bigint,
|
||||
email_address text NOT NULL,
|
||||
registry_lock_password_hash text,
|
||||
registry_lock_password_salt text,
|
||||
@@ -1340,7 +1339,7 @@ CREATE TABLE public."UserUpdateHistory" (
|
||||
history_request_body text,
|
||||
history_type text NOT NULL,
|
||||
history_url text NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
user_id bigint,
|
||||
email_address text NOT NULL,
|
||||
registry_lock_password_hash text,
|
||||
registry_lock_password_salt text,
|
||||
@@ -1833,7 +1832,7 @@ ALTER TABLE ONLY public."UserUpdateHistory"
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."User"
|
||||
ADD CONSTRAINT "User_pkey" PRIMARY KEY (id);
|
||||
ADD CONSTRAINT "User_pkey" PRIMARY KEY (email_address);
|
||||
|
||||
|
||||
--
|
||||
@@ -2512,13 +2511,6 @@ CREATE INDEX registrar_iana_identifier_idx ON public."Registrar" USING btree (ia
|
||||
CREATE INDEX registrar_name_idx ON public."Registrar" USING btree (registrar_name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: registrarpoc_login_email_idx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX registrarpoc_login_email_idx ON public."RegistrarPoc" USING btree (login_email_address);
|
||||
|
||||
|
||||
--
|
||||
-- Name: reservedlist_name_idx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -2547,13 +2539,6 @@ CREATE INDEX spec11threatmatch_registrar_id_idx ON public."Spec11ThreatMatch" US
|
||||
CREATE INDEX spec11threatmatch_tld_idx ON public."Spec11ThreatMatch" USING btree (tld);
|
||||
|
||||
|
||||
--
|
||||
-- Name: user_email_address_idx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX user_email_address_idx ON public."User" USING btree (email_address);
|
||||
|
||||
|
||||
--
|
||||
-- Name: UserUpdateHistory fk1s7bopbl3pwrhv3jkkofnv3o0; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||