Skip to content
Snippets Groups Projects
Verified Commit cc0f9783 authored by Martin Weise's avatar Martin Weise
Browse files

More tests

parent 96dc0716
No related branches found
No related tags found
7 merge requests!345Updated docs and endpoints:,!341Fixed mapping problem where UK and FK share columns they are inserted,!339Fixed mapping problem where UK and FK share columns they are inserted,!338Fixed mapping problem where UK and FK share columns they are inserted,!334Fixed mapping problem where UK and FK share columns they are inserted,!333Fixed mapping problem where UK and FK share columns they are inserted,!328Hotfix/mapping
...@@ -68,17 +68,37 @@ public class EndpointValidator { ...@@ -68,17 +68,37 @@ public class EndpointValidator {
if (data == null) { if (data == null) {
throw new MalformedException("Validation failed: table data is null"); throw new MalformedException("Validation failed: table data is null");
} }
final List<ColumnTypeDto> needSize = List.of(ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY);
final List<ColumnTypeDto> canHaveSize = List.of(ColumnTypeDto.CHAR, ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY, ColumnTypeDto.BIT, ColumnTypeDto.TINYINT, ColumnTypeDto.SMALLINT, ColumnTypeDto.MEDIUMINT, ColumnTypeDto.INT); final List<ColumnTypeDto> canHaveSize = List.of(ColumnTypeDto.CHAR, ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY, ColumnTypeDto.BIT, ColumnTypeDto.TINYINT, ColumnTypeDto.SMALLINT, ColumnTypeDto.MEDIUMINT, ColumnTypeDto.INT);
final List<ColumnTypeDto> canHaveSizeAndD = List.of(ColumnTypeDto.DOUBLE, ColumnTypeDto.DECIMAL); final List<ColumnTypeDto> canHaveSizeAndD = List.of(ColumnTypeDto.DOUBLE, ColumnTypeDto.DECIMAL);
/* check size */ /* check size */
final Optional<ColumnCreateDto> optional0 = data.getColumns() final Optional<ColumnCreateDto> optional0 = data.getColumns()
.stream()
.filter(c -> Objects.isNull(c.getSize()))
.filter(c -> needSize.contains(c.getType()))
.findFirst();
if (optional0.isPresent()) {
log.error("Validation failed: column {} need size parameter", optional0.get().getName());
throw new MalformedException("Validation failed: column " + optional0.get().getName() + " need size parameter");
}
final Optional<ColumnCreateDto> optional0a = data.getColumns()
.stream()
.filter(c -> !Objects.isNull(c.getSize()))
.filter(c -> canHaveSize.contains(c.getType()))
.filter(c -> c.getSize() < 0)
.findFirst();
if (optional0a.isPresent()) {
log.error("Validation failed: column {} needs positive size parameter", optional0a.get().getName());
throw new MalformedException("Validation failed: column " + optional0a.get().getName() + " needs positive size parameter");
}
final Optional<ColumnCreateDto> optional0b = data.getColumns()
.stream() .stream()
.filter(c -> !Objects.isNull(c.getSize())) .filter(c -> !Objects.isNull(c.getSize()))
.filter(c -> !canHaveSize.contains(c.getType())) .filter(c -> !canHaveSize.contains(c.getType()))
.findFirst(); .findFirst();
if (optional0.isPresent()) { if (optional0b.isPresent()) {
log.error("Validation failed: column {} cannot have size parameter", optional0.get().getName()); log.error("Validation failed: column {} cannot have size parameter", optional0b.get().getName());
throw new MalformedException("Validation failed: column " + optional0.get().getName() + " cannot have size parameter"); throw new MalformedException("Validation failed: column " + optional0b.get().getName() + " cannot have size parameter");
} }
/* check size and d */ /* check size and d */
final Optional<ColumnCreateDto> optional1 = data.getColumns() final Optional<ColumnCreateDto> optional1 = data.getColumns()
......
package at.tuwien.endpoints; package at.tuwien.endpoints;
import at.tuwien.mapper.MetadataMapper;
import at.tuwien.test.AbstractUnitTest;
import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.AccessTypeDto;
import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.DatabaseAccessDto;
import at.tuwien.entities.database.Database; import at.tuwien.entities.database.Database;
import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.database.DatabaseAccess;
import at.tuwien.entities.user.User; import at.tuwien.entities.user.User;
import at.tuwien.exception.*; import at.tuwien.exception.*;
import at.tuwien.mapper.MetadataMapper;
import at.tuwien.repository.DatabaseRepository; import at.tuwien.repository.DatabaseRepository;
import at.tuwien.repository.UserRepository; import at.tuwien.repository.UserRepository;
import at.tuwien.service.AccessService; import at.tuwien.service.AccessService;
import at.tuwien.test.AbstractUnitTest;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
...@@ -57,7 +57,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -57,7 +57,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
/* test */ /* test */
assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
generic_create(null, USER_2_ID, null, null); generic_create(null, null, null, null);
}); });
} }
...@@ -67,7 +67,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -67,7 +67,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
/* test */ /* test */
assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
generic_create(USER_2_PRINCIPAL, USER_4_ID, USER_4_USERNAME, USER_4); generic_create(USER_2_PRINCIPAL, USER_2, USER_4_ID, USER_4);
}); });
} }
...@@ -82,7 +82,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -82,7 +82,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
.thenReturn(DATABASE_1_USER_1_READ_ACCESS); .thenReturn(DATABASE_1_USER_1_READ_ACCESS);
/* test */ /* test */
generic_create(USER_2_PRINCIPAL, USER_2_ID, USER_2_USERNAME, USER_2); generic_create(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2);
} }
@Test @Test
...@@ -129,7 +129,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -129,7 +129,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
/* test */ /* test */
assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
generic_update(null, USER_4_USERNAME, USER_4, null, null); generic_update(null, null, null, null, null);
}); });
} }
...@@ -138,8 +138,8 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -138,8 +138,8 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
public void update_hasRoleNoAccess_fails() { public void update_hasRoleNoAccess_fails() {
/* test */ /* test */
assertThrows(NotAllowedException.class, () -> { assertThrows(AccessNotFoundException.class, () -> {
generic_update(null, USER_4_USERNAME, USER_4, USER_1_PRINCIPAL, USER_1); generic_update(USER_1_PRINCIPAL, USER_1, USER_4_ID, USER_4, null);
}); });
} }
...@@ -149,7 +149,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -149,7 +149,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
/* test */ /* test */
assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
generic_update(null, USER_4_USERNAME, USER_4, USER_4_PRINCIPAL, USER_4); generic_update(USER_4_PRINCIPAL, USER_4, USER_1_ID, USER_1, null);
}); });
} }
...@@ -165,7 +165,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -165,7 +165,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
.update(eq(DATABASE_1), eq(USER_2), any(AccessTypeDto.class)); .update(eq(DATABASE_1), eq(USER_2), any(AccessTypeDto.class));
/* test */ /* test */
generic_update(DATABASE_1_USER_2_WRITE_OWN_ACCESS, USER_2_USERNAME, USER_2, USER_2_PRINCIPAL, USER_2); generic_update(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2, DATABASE_1_USER_2_WRITE_OWN_ACCESS);
} }
@Test @Test
...@@ -174,7 +174,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -174,7 +174,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
/* test */ /* test */
assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
generic_revoke(USER_1_PRINCIPAL, USER_1); generic_revoke(null, null, USER_1_ID, USER_1);
}); });
} }
...@@ -184,7 +184,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -184,7 +184,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
/* test */ /* test */
assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
generic_revoke(USER_4_PRINCIPAL, USER_4); generic_revoke(USER_4_PRINCIPAL, USER_4, USER_1_ID, USER_1);
}); });
} }
...@@ -200,14 +200,14 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -200,14 +200,14 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
.delete(DATABASE_1, USER_2); .delete(DATABASE_1, USER_2);
/* test */ /* test */
generic_revoke(USER_1_PRINCIPAL, USER_1); generic_revoke(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2);
} }
/* ################################################################################################### */ /* ################################################################################################### */
/* ## GENERIC TEST CASES ## */ /* ## GENERIC TEST CASES ## */
/* ################################################################################################### */ /* ################################################################################################### */
protected void generic_create(Principal principal, UUID userId, String username, User user) protected void generic_create(Principal principal, User principalUser, UUID userId, User user)
throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException,
DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException,
SearchServiceConnectionException { SearchServiceConnectionException {
...@@ -218,11 +218,18 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -218,11 +218,18 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
doThrow(AccessNotFoundException.class) doThrow(AccessNotFoundException.class)
.when(accessService) .when(accessService)
.find(DATABASE_1, user); .find(DATABASE_1, user);
if (principalUser != null) {
when(userRepository.findByUsername(principal.getName()))
.thenReturn(Optional.of(principalUser));
} else {
when(userRepository.findByUsername(anyString()))
.thenReturn(Optional.empty());
}
if (user != null) { if (user != null) {
when(userRepository.findByUsername(username)) when(userRepository.findById(userId))
.thenReturn(Optional.of(user)); .thenReturn(Optional.of(user));
} else { } else {
when(userRepository.findByUsername(anyString())) when(userRepository.findById(any(UUID.class)))
.thenReturn(Optional.empty()); .thenReturn(Optional.empty());
} }
...@@ -268,61 +275,62 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { ...@@ -268,61 +275,62 @@ public class AccessEndpointUnitTest extends AbstractUnitTest {
} }
} }
protected void generic_update(DatabaseAccess access, String otherUsername, User otherUser, Principal principal, protected void generic_update(Principal principal, User principalUser, UUID userId, User user,
User user) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseAccess access) throws NotAllowedException, DataServiceException,
AccessNotFoundException, UserNotFoundException, DatabaseNotFoundException, SearchServiceException, DataServiceConnectionException, AccessNotFoundException, UserNotFoundException, DatabaseNotFoundException,
SearchServiceConnectionException { SearchServiceException, SearchServiceConnectionException {
/* mock */ /* mock */
when(databaseRepository.findById(DATABASE_1_ID)) when(databaseRepository.findById(DATABASE_1_ID))
.thenReturn(Optional.of(DATABASE_1)); .thenReturn(Optional.of(DATABASE_1));
if (access != null) { if (access != null) {
log.trace("mock access {} for user with id {} for database with id {}", access.getType(), USER_1_ID, DATABASE_1_ID); log.trace("mock access {} for user with id {} for database with id {}", access.getType(), userId, DATABASE_1_ID);
when(accessService.find(DATABASE_1, USER_1)) when(accessService.find(DATABASE_1, user))
.thenReturn(access); .thenReturn(access);
} else { } else {
log.trace("mock no access for user with id {} for database with id {}", USER_1_ID, DATABASE_1_ID); log.trace("mock no access for user with id {} for database with id {}", userId, DATABASE_1_ID);
doThrow(AccessNotFoundException.class) doThrow(AccessNotFoundException.class)
.when(accessService) .when(accessService)
.find(DATABASE_1, USER_1); .find(DATABASE_1, user);
} }
if (otherUsername != null) { if (userId != null) {
when(userRepository.findByUsername(otherUsername)) when(userRepository.findById(userId))
.thenReturn(Optional.of(otherUser)); .thenReturn(Optional.of(user));
} else { } else {
when(userRepository.findByUsername(anyString())) when(userRepository.findById(any(UUID.class)))
.thenReturn(Optional.empty()); .thenReturn(Optional.empty());
} }
if (principal != null) { if (principal != null) {
when(userRepository.findByUsername(principal.getName())) when(userRepository.findByUsername(principal.getName()))
.thenReturn(Optional.of(user)); .thenReturn(Optional.of(principalUser));
} else { } else {
when(userRepository.findByUsername(anyString())) when(userRepository.findByUsername(anyString()))
.thenReturn(Optional.empty()); .thenReturn(Optional.empty());
} }
/* test */ /* test */
final ResponseEntity<?> response = accessEndpoint.update(DATABASE_1_ID, USER_1_ID, UPDATE_DATABASE_ACCESS_READ_DTO, principal); final ResponseEntity<?> response = accessEndpoint.update(DATABASE_1_ID, userId, UPDATE_DATABASE_ACCESS_READ_DTO, principal);
assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
assertNull(response.getBody()); assertNull(response.getBody());
} }
protected void generic_revoke(Principal principal, User user) throws DataServiceConnectionException, protected void generic_revoke(Principal principal, User principalUser, UUID userId, User user)
NotAllowedException, DataServiceException, UserNotFoundException, DatabaseNotFoundException, throws DataServiceConnectionException, NotAllowedException, DataServiceException, UserNotFoundException,
AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { DatabaseNotFoundException, AccessNotFoundException, SearchServiceException,
SearchServiceConnectionException {
/* mock */ /* mock */
when(accessService.find(any(Database.class), eq(user)))
.thenReturn(DATABASE_1_USER_1_READ_ACCESS);
when(databaseRepository.findById(DATABASE_1_ID)) when(databaseRepository.findById(DATABASE_1_ID))
.thenReturn(Optional.of(DATABASE_1)); .thenReturn(Optional.of(DATABASE_1));
if (principal != null) { if (principal != null) {
when(userRepository.findByUsername(principal.getName())) when(userRepository.findByUsername(principal.getName()))
.thenReturn(Optional.of(user)); .thenReturn(Optional.of(principalUser));
} }
when(userRepository.findById(userId))
.thenReturn(Optional.of(user));
/* test */ /* test */
final ResponseEntity<?> response = accessEndpoint.revoke(DATABASE_1_ID, USER_1_ID, principal); final ResponseEntity<?> response = accessEndpoint.revoke(DATABASE_1_ID, userId, principal);
assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
assertNull(response.getBody()); assertNull(response.getBody());
} }
......
...@@ -167,101 +167,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { ...@@ -167,101 +167,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest {
}); });
} }
@Test
@WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"})
public void create_publicDecimalColumnSizeMissing_fails() {
final TableCreateDto request = TableCreateDto.builder()
.name("Some Table")
.description("Some Description")
.columns(List.of(ColumnCreateDto.builder()
.name("ID")
.type(ColumnTypeDto.DECIMAL)
.build()))
.constraints(null)
.build();
/* test */
assertThrows(MalformedException.class, () -> {
generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS);
});
}
@Test
@WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"})
public void create_publicDateFormatMissing_fails() {
final TableCreateDto request = TableCreateDto.builder()
.name("Some Table")
.description("Some Description")
.columns(List.of(ColumnCreateDto.builder()
.name("timestamp")
.type(ColumnTypeDto.DATE)
.build()))
.constraints(null)
.build();
/* test */
assertThrows(MalformedException.class, () -> {
generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS);
});
}
@Test
@WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"})
public void create_publicDateTimeFormatMissing_fails() {
final TableCreateDto request = TableCreateDto.builder()
.name("Some Table")
.description("Some Description")
.columns(List.of(ColumnCreateDto.builder()
.name("timestamp")
.type(ColumnTypeDto.DATETIME)
.build()))
.constraints(null)
.build();
/* test */
assertThrows(MalformedException.class, () -> {
generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS);
});
}
@Test
@WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"})
public void create_publicTimeFormatMissing_fails() {
final TableCreateDto request = TableCreateDto.builder()
.name("Some Table")
.description("Some Description")
.columns(List.of(ColumnCreateDto.builder()
.name("timestamp")
.type(ColumnTypeDto.TIME)
.build()))
.constraints(null)
.build();
/* test */
assertThrows(MalformedException.class, () -> {
generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS);
});
}
@Test
@WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"})
public void create_publicTimestampFormatMissing_fails() {
final TableCreateDto request = TableCreateDto.builder()
.name("Some Table")
.description("Some Description")
.columns(List.of(ColumnCreateDto.builder()
.name("timestamp")
.type(ColumnTypeDto.TIMESTAMP)
.build()))
.constraints(null)
.build();
/* test */
assertThrows(MalformedException.class, () -> {
generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS);
});
}
@Test @Test
@WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"})
public void create_publicDecimalColumnSizeTooSmall_fails() { public void create_publicDecimalColumnSizeTooSmall_fails() {
......
...@@ -53,22 +53,9 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { ...@@ -53,22 +53,9 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest {
public static Stream<Arguments> needSize_parameters() { public static Stream<Arguments> needSize_parameters() {
return Stream.of( return Stream.of(
Arguments.arguments(ColumnTypeDto.CHAR),
Arguments.arguments(ColumnTypeDto.VARCHAR), Arguments.arguments(ColumnTypeDto.VARCHAR),
Arguments.arguments(ColumnTypeDto.BINARY), Arguments.arguments(ColumnTypeDto.BINARY),
Arguments.arguments(ColumnTypeDto.VARBINARY), Arguments.arguments(ColumnTypeDto.VARBINARY)
Arguments.arguments(ColumnTypeDto.BIT),
Arguments.arguments(ColumnTypeDto.TINYINT),
Arguments.arguments(ColumnTypeDto.SMALLINT),
Arguments.arguments(ColumnTypeDto.MEDIUMINT),
Arguments.arguments(ColumnTypeDto.INT)
);
}
public static Stream<Arguments> needSizeAndD_parameters() {
return Stream.of(
Arguments.arguments(ColumnTypeDto.DOUBLE),
Arguments.arguments(ColumnTypeDto.DECIMAL)
); );
} }
...@@ -300,23 +287,6 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { ...@@ -300,23 +287,6 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest {
}); });
} }
@ParameterizedTest
@MethodSource("needSizeAndD_parameters")
public void validateColumnCreateConstraints_needSizeAndD_fails(ColumnTypeDto type) {
final TableCreateDto request = TableCreateDto.builder()
.columns(List.of(ColumnCreateDto.builder()
.type(type)
.size(10L)
.d(null) // <<<<<<<
.build()))
.build();
/* test */
assertThrows(MalformedException.class, () -> {
endpointValidator.validateColumnCreateConstraints(request);
});
}
@Test @Test
public void validateColumnCreateConstraints_needEnum_fails() { public void validateColumnCreateConstraints_needEnum_fails() {
final TableCreateDto request = TableCreateDto.builder() final TableCreateDto request = TableCreateDto.builder()
......
...@@ -196,6 +196,9 @@ export const useQueryService = (): any => { ...@@ -196,6 +196,9 @@ export const useQueryService = (): any => {
return {timestamp, page, size} return {timestamp, page, size}
} }
/**
* data types with non-null defaultSize values require size to be set
*/
function mySql8DataTypes(): MySql8DataType[] { function mySql8DataTypes(): MySql8DataType[] {
return [ return [
{value: 'bigint', text: 'BIGINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: null}, {value: 'bigint', text: 'BIGINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: null},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment