mirror of
https://github.com/google/nomulus.git
synced 2025-05-03 21:47:51 +02:00
Add DB annotations to console User and related classes (#1757)
We added the DB code last week, this is the corresponding bit now that that has been released.
This commit is contained in:
parent
700b3abc80
commit
fae38ce389
8 changed files with 219 additions and 2 deletions
|
@ -24,20 +24,34 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||||
|
|
||||||
import google.registry.model.Buildable;
|
import google.registry.model.Buildable;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
/** A console user, either a registry employee or a registrar partner. */
|
/** A console user, either a registry employee or a registrar partner. */
|
||||||
|
@Entity
|
||||||
|
@Table(
|
||||||
|
indexes = {
|
||||||
|
@Index(columnList = "gaiaId", name = "user_gaia_id_idx"),
|
||||||
|
@Index(columnList = "emailAddress", name = "user_email_address_idx")
|
||||||
|
})
|
||||||
public class User extends ImmutableObject implements Buildable {
|
public class User extends ImmutableObject implements Buildable {
|
||||||
|
|
||||||
/** Autogenerated unique ID of this user. */
|
/** Autogenerated unique ID of this user. */
|
||||||
private long id;
|
@Id private long id;
|
||||||
|
|
||||||
/** GAIA ID associated with the user in question. */
|
/** GAIA ID associated with the user in question. */
|
||||||
|
@Column(nullable = false)
|
||||||
private String gaiaId;
|
private String gaiaId;
|
||||||
|
|
||||||
/** Email address of the user in question. */
|
/** Email address of the user in question. */
|
||||||
|
@Column(nullable = false)
|
||||||
private String emailAddress;
|
private String emailAddress;
|
||||||
|
|
||||||
/** Roles (which grant permissions) associated with this user. */
|
/** Roles (which grant permissions) associated with this user. */
|
||||||
|
@Column(nullable = false)
|
||||||
private UserRoles userRoles;
|
private UserRoles userRoles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,10 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.Buildable;
|
import google.registry.model.Buildable;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the global and per-registrar roles for a given user.
|
* Contains the global and per-registrar roles for a given user.
|
||||||
|
@ -28,15 +32,19 @@ import java.util.Map;
|
||||||
* <p>See <a href="https://go/nomulus-console-authz">go/nomulus-console-authz</a> for more
|
* <p>See <a href="https://go/nomulus-console-authz">go/nomulus-console-authz</a> for more
|
||||||
* information.
|
* information.
|
||||||
*/
|
*/
|
||||||
|
@Embeddable
|
||||||
public class UserRoles extends ImmutableObject implements Buildable {
|
public class UserRoles extends ImmutableObject implements Buildable {
|
||||||
|
|
||||||
/** Whether the user is a global admin, who has access to everything. */
|
/** Whether the user is a global admin, who has access to everything. */
|
||||||
|
@Column(nullable = false)
|
||||||
private boolean isAdmin = false;
|
private boolean isAdmin = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The global role (e.g. {@link GlobalRole#SUPPORT_AGENT}) that the user has across all
|
* The global role (e.g. {@link GlobalRole#SUPPORT_AGENT}) that the user has across all
|
||||||
* registrars.
|
* registrars.
|
||||||
*/
|
*/
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(nullable = false)
|
||||||
private GlobalRole globalRole = GlobalRole.NONE;
|
private GlobalRole globalRole = GlobalRole.NONE;
|
||||||
|
|
||||||
/** Any per-registrar roles that this user may have. */
|
/** Any per-registrar roles that this user may have. */
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// 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.persistence.converter;
|
||||||
|
|
||||||
|
import google.registry.model.console.RegistrarRole;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Converter;
|
||||||
|
|
||||||
|
/** JPA converter for storing / retrieving {@code Map<String, RegistrarRole>} objects. */
|
||||||
|
@Converter(autoApply = true)
|
||||||
|
public class RegistrarToRoleConverter
|
||||||
|
extends StringMapConverterBase<String, RegistrarRole, Map<String, RegistrarRole>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String convertKeyToString(String key) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String convertValueToString(RegistrarRole value) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String convertStringToKey(String string) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RegistrarRole convertStringToValue(String string) {
|
||||||
|
return RegistrarRole.valueOf(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, RegistrarRole> convertMapToDerivedType(Map<String, RegistrarRole> map) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,7 @@
|
||||||
<class>google.registry.model.billing.BillingEvent$Recurring</class>
|
<class>google.registry.model.billing.BillingEvent$Recurring</class>
|
||||||
<class>google.registry.model.common.Cursor</class>
|
<class>google.registry.model.common.Cursor</class>
|
||||||
<class>google.registry.model.common.DatabaseMigrationStateSchedule</class>
|
<class>google.registry.model.common.DatabaseMigrationStateSchedule</class>
|
||||||
|
<class>google.registry.model.console.User</class>
|
||||||
<class>google.registry.model.contact.ContactHistory</class>
|
<class>google.registry.model.contact.ContactHistory</class>
|
||||||
<class>google.registry.model.contact.ContactResource</class>
|
<class>google.registry.model.contact.ContactResource</class>
|
||||||
<class>google.registry.model.domain.Domain</class>
|
<class>google.registry.model.domain.Domain</class>
|
||||||
|
@ -91,6 +92,7 @@
|
||||||
<class>google.registry.persistence.converter.LocalDateConverter</class>
|
<class>google.registry.persistence.converter.LocalDateConverter</class>
|
||||||
<class>google.registry.persistence.converter.PostalInfoChoiceListConverter</class>
|
<class>google.registry.persistence.converter.PostalInfoChoiceListConverter</class>
|
||||||
<class>google.registry.persistence.converter.RegistrarPocSetConverter</class>
|
<class>google.registry.persistence.converter.RegistrarPocSetConverter</class>
|
||||||
|
<class>google.registry.persistence.converter.RegistrarToRoleConverter</class>
|
||||||
<class>google.registry.persistence.converter.Spec11ThreatMatchThreatTypeSetConverter</class>
|
<class>google.registry.persistence.converter.Spec11ThreatMatchThreatTypeSetConverter</class>
|
||||||
<class>google.registry.persistence.converter.StatusValueSetConverter</class>
|
<class>google.registry.persistence.converter.StatusValueSetConverter</class>
|
||||||
<class>google.registry.persistence.converter.StringListConverter</class>
|
<class>google.registry.persistence.converter.StringListConverter</class>
|
||||||
|
|
|
@ -15,12 +15,71 @@
|
||||||
package google.registry.model.console;
|
package google.registry.model.console;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||||
|
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import google.registry.model.EntityTestCase;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/** Tests for {@link User}. */
|
/** Tests for {@link User}. */
|
||||||
public class UserTest {
|
public class UserTest extends EntityTestCase {
|
||||||
|
|
||||||
|
UserTest() {
|
||||||
|
super(JpaEntityCoverageCheck.ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPersistence_lookupByEmail() {
|
||||||
|
User user =
|
||||||
|
new User.Builder()
|
||||||
|
.setGaiaId("gaiaId")
|
||||||
|
.setEmailAddress("email@email.com")
|
||||||
|
.setUserRoles(
|
||||||
|
new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).setIsAdmin(true).build())
|
||||||
|
.build();
|
||||||
|
persistResource(user);
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
assertThat(
|
||||||
|
jpaTm()
|
||||||
|
.query("FROM User WHERE emailAddress = 'email@email.com'", User.class)
|
||||||
|
.getSingleResult())
|
||||||
|
.isEqualTo(user);
|
||||||
|
assertThat(
|
||||||
|
jpaTm()
|
||||||
|
.query("FROM User WHERE emailAddress = 'bad@fake.com'", User.class)
|
||||||
|
.getResultList())
|
||||||
|
.isEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPersistence_lookupByGaiaId() {
|
||||||
|
User user =
|
||||||
|
new User.Builder()
|
||||||
|
.setGaiaId("gaiaId")
|
||||||
|
.setEmailAddress("email@email.com")
|
||||||
|
.setUserRoles(
|
||||||
|
new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).setIsAdmin(true).build())
|
||||||
|
.build();
|
||||||
|
persistResource(user);
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
assertThat(
|
||||||
|
jpaTm()
|
||||||
|
.query("FROM User WHERE gaiaId = 'gaiaId'", User.class)
|
||||||
|
.getSingleResult())
|
||||||
|
.isEqualTo(user);
|
||||||
|
assertThat(
|
||||||
|
jpaTm()
|
||||||
|
.query("FROM User WHERE gaiaId = 'badGaiaId'", User.class)
|
||||||
|
.getResultList())
|
||||||
|
.isEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testFailure_badInputs() {
|
void testFailure_badInputs() {
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// 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.persistence.converter;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import google.registry.model.ImmutableObject;
|
||||||
|
import google.registry.model.console.RegistrarRole;
|
||||||
|
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||||
|
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||||
|
import google.registry.testing.DatabaseHelper;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
/** Tests for {@link RegistrarToRoleConverter}. */
|
||||||
|
public class RegistrarToRoleConverterTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final JpaUnitTestExtension jpa =
|
||||||
|
new JpaTestExtensions.Builder().withEntityClass(TestEntity.class).buildUnitTestExtension();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRoundTripConversion() {
|
||||||
|
Map<String, RegistrarRole> map =
|
||||||
|
ImmutableMap.of(
|
||||||
|
"TheRegistrar",
|
||||||
|
RegistrarRole.ACCOUNT_MANAGER,
|
||||||
|
"NewRegistrar",
|
||||||
|
RegistrarRole.PRIMARY_CONTACT,
|
||||||
|
"FooRegistrar",
|
||||||
|
RegistrarRole.TECH_CONTACT);
|
||||||
|
TestEntity entity = new TestEntity(map);
|
||||||
|
DatabaseHelper.insertInDb(entity);
|
||||||
|
TestEntity persisted = Iterables.getOnlyElement(DatabaseHelper.loadAllOf(TestEntity.class));
|
||||||
|
assertThat(persisted.map).isEqualTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "TestEntity")
|
||||||
|
private static class TestEntity extends ImmutableObject {
|
||||||
|
|
||||||
|
@Id String name = "id";
|
||||||
|
|
||||||
|
Map<String, RegistrarRole> map;
|
||||||
|
|
||||||
|
private TestEntity() {}
|
||||||
|
|
||||||
|
private TestEntity(Map<String, RegistrarRole> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assert_;
|
||||||
|
|
||||||
import google.registry.model.billing.BillingEventTest;
|
import google.registry.model.billing.BillingEventTest;
|
||||||
import google.registry.model.common.CursorTest;
|
import google.registry.model.common.CursorTest;
|
||||||
|
import google.registry.model.console.UserTest;
|
||||||
import google.registry.model.contact.ContactResourceTest;
|
import google.registry.model.contact.ContactResourceTest;
|
||||||
import google.registry.model.domain.DomainSqlTest;
|
import google.registry.model.domain.DomainSqlTest;
|
||||||
import google.registry.model.domain.token.AllocationTokenTest;
|
import google.registry.model.domain.token.AllocationTokenTest;
|
||||||
|
@ -101,6 +102,7 @@ import org.junit.runner.RunWith;
|
||||||
SignedMarkRevocationListDaoTest.class,
|
SignedMarkRevocationListDaoTest.class,
|
||||||
Spec11ThreatMatchTest.class,
|
Spec11ThreatMatchTest.class,
|
||||||
TmchCrlTest.class,
|
TmchCrlTest.class,
|
||||||
|
UserTest.class,
|
||||||
// AfterSuiteTest must be the last entry. See class javadoc for details.
|
// AfterSuiteTest must be the last entry. See class javadoc for details.
|
||||||
AfterSuiteTest.class
|
AfterSuiteTest.class
|
||||||
})
|
})
|
||||||
|
|
|
@ -740,6 +740,18 @@
|
||||||
url text not null,
|
url text not null,
|
||||||
primary key (id)
|
primary key (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table "User" (
|
||||||
|
id int8 not null,
|
||||||
|
email_address text not null,
|
||||||
|
gaia_id text not null,
|
||||||
|
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)
|
||||||
|
);
|
||||||
create index allocation_token_domain_name_idx on "AllocationToken" (domain_name);
|
create index allocation_token_domain_name_idx on "AllocationToken" (domain_name);
|
||||||
create index IDX9g3s7mjv1yn4t06nqid39whss on "AllocationToken" (token_type);
|
create index IDX9g3s7mjv1yn4t06nqid39whss on "AllocationToken" (token_type);
|
||||||
create index IDXtmlqd31dpvvd2g1h9i7erw6aj on "AllocationToken" (redemption_domain_repo_id);
|
create index IDXtmlqd31dpvvd2g1h9i7erw6aj on "AllocationToken" (redemption_domain_repo_id);
|
||||||
|
@ -825,6 +837,8 @@ create index reservedlist_name_idx on "ReservedList" (name);
|
||||||
create index spec11threatmatch_registrar_id_idx on "Spec11ThreatMatch" (registrar_id);
|
create index spec11threatmatch_registrar_id_idx on "Spec11ThreatMatch" (registrar_id);
|
||||||
create index spec11threatmatch_tld_idx on "Spec11ThreatMatch" (tld);
|
create index spec11threatmatch_tld_idx on "Spec11ThreatMatch" (tld);
|
||||||
create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date);
|
create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date);
|
||||||
|
create index user_gaia_id_idx on "User" (gaia_id);
|
||||||
|
create index user_email_address_idx on "User" (email_address);
|
||||||
|
|
||||||
alter table if exists "DelegationSignerData"
|
alter table if exists "DelegationSignerData"
|
||||||
add constraint FKtr24j9v14ph2mfuw2gsmt12kq
|
add constraint FKtr24j9v14ph2mfuw2gsmt12kq
|
||||||
|
|
Loading…
Add table
Reference in a new issue