Skip to content

Commit

Permalink
Merge branch 'master' into DHIS2-14428
Browse files Browse the repository at this point in the history
  • Loading branch information
david-mackessy committed Oct 25, 2024
2 parents a582eff + fef14c6 commit 72c4f5b
Show file tree
Hide file tree
Showing 77 changed files with 1,043 additions and 797 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,17 @@ public class AssignedUserQueryParam {
public static final AssignedUserQueryParam ALL =
new AssignedUserQueryParam(AssignedUserSelectionMode.ALL, Collections.emptySet(), null);

private final AssignedUserSelectionMode mode;
AssignedUserSelectionMode mode;

private final Set<String> assignedUsers;
Set<UID> assignedUsers;

/**
* Non-empty assigned users are only allowed with mode PROVIDED (or null).
*
* @param mode assigned user mode
* @param assignedUsers assigned user uids
*/
public AssignedUserQueryParam(
AssignedUserSelectionMode mode, Set<String> assignedUsers, String userUid) {
public AssignedUserQueryParam(AssignedUserSelectionMode mode, Set<UID> assignedUsers, UID user) {
if (mode == AssignedUserSelectionMode.PROVIDED
&& (assignedUsers == null || assignedUsers.isEmpty())) {
throw new IllegalQueryException(
Expand All @@ -69,7 +68,7 @@ public AssignedUserQueryParam(

if (mode == AssignedUserSelectionMode.CURRENT) {
this.mode = AssignedUserSelectionMode.PROVIDED;
this.assignedUsers = Collections.singleton(userUid);
this.assignedUsers = Collections.singleton(user);
} else if ((mode == null || mode == AssignedUserSelectionMode.PROVIDED)
&& (assignedUsers != null && !assignedUsers.isEmpty())) {
this.mode = AssignedUserSelectionMode.PROVIDED;
Expand Down
32 changes: 19 additions & 13 deletions dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/OpenApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,19 +163,6 @@ enum Access {
String value();
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Team {

/**
* Names are case-insensitive, e.g. "Tracker" is the same as "tracker"
*
* @return name of the team that supports the annotated element
*/
String value();
}

/**
* Can be used to annotate endpoint methods to constraint which concrete {@link EntityType}s will
* support the annotated endpoint method.
Expand All @@ -198,6 +185,10 @@ enum Access {
Class<?>[] excludes() default {};
}

/**
* Used to classify the contents of a controller so that the entire API can be split by the
* different classifiers.
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Document {
Expand All @@ -218,9 +209,13 @@ enum Access {
* named of the domain class. That is the {@link Class#getSimpleName()} unless the class is
* annotated and named via {@link Shared}.
*
* <p>Unless overridden by {@link #classifiers()} this is also the classifier value for {@code
* entity}.
*
* @return the class that represents the domain for the annotated controller {@link Class} or
* endpoint {@link java.lang.reflect.Method}.
*/
// TODO rename to entity() (extra PR)
Class<?> domain() default EntityType.class;

/**
Expand All @@ -230,6 +225,17 @@ enum Access {
* @return type of group used
*/
String group() default "";

/**
*
*
* <pre>
* {"team:tracker", "purpose:metadata", "path:/openapi"}
* </pre>
*
* @return the scope classifiers that describe the annotated controller
*/
String[] classifiers() default {};
}

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
Expand Down
9 changes: 9 additions & 0 deletions dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/UID.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import javax.annotation.Nonnull;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.hisp.dhis.user.SystemUser;
import org.hisp.dhis.user.UserDetails;

/**
Expand Down Expand Up @@ -78,13 +79,21 @@ public static UID of(@Nonnull String value) {
}

public static UID of(@Nonnull UserDetails currentUser) {
// TODO:(DHIS2-18296) Refactor SystemUser to use a valid uid
if (currentUser instanceof SystemUser) {
return new UID("systemUser1");
}
return new UID(currentUser.getUid());
}

public static UID of(@CheckForNull UidObject object) {
return object == null ? null : new UID(object.getUid());
}

public static Set<UID> of(@Nonnull String... values) {
return Stream.of(values).map(UID::of).collect(toUnmodifiableSet());
}

public static Set<UID> of(@Nonnull Collection<String> values) {
return values.stream().map(UID::of).collect(toUnmodifiableSet());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hisp.dhis.common.OpenApi;
import org.hisp.dhis.webmessage.BasicWebMessage;
import org.hisp.dhis.webmessage.WebResponse;

@Getter
@Accessors(chain = true)
@OpenApi.Response(status = BAD_REQUEST, value = BasicWebMessage.class)
@OpenApi.Response(status = BAD_REQUEST, value = WebResponse.class)
@SuppressWarnings({"java:S1165", "java:S1948"})
public final class BadRequestException extends Exception implements Error {
public static <E extends RuntimeException, V> V on(Class<E> type, Supplier<V> operation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hisp.dhis.common.OpenApi;
import org.hisp.dhis.webmessage.BasicWebMessage;
import org.hisp.dhis.webmessage.WebResponse;

@Getter
@Accessors(chain = true)
@OpenApi.Response(status = CONFLICT, value = BasicWebMessage.class)
@OpenApi.Response(status = CONFLICT, value = WebResponse.class)
@SuppressWarnings({"java:S1165", "java:S1948"})
public final class ConflictException extends Exception implements Error {
public static <E extends RuntimeException, V> V on(Class<E> type, Supplier<V> operation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
import lombok.Getter;
import lombok.experimental.Accessors;
import org.hisp.dhis.common.OpenApi;
import org.hisp.dhis.webmessage.BasicWebMessage;
import org.hisp.dhis.webmessage.WebResponse;

@Getter
@Accessors(chain = true)
@OpenApi.Response(status = FORBIDDEN, value = BasicWebMessage.class)
@OpenApi.Response(status = FORBIDDEN, value = WebResponse.class)
public final class ForbiddenException extends Exception implements Error {
public static <E extends RuntimeException, V> V on(Class<E> type, Supplier<V> operation)
throws ForbiddenException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
import lombok.Getter;
import lombok.experimental.Accessors;
import org.hisp.dhis.common.OpenApi;
import org.hisp.dhis.webmessage.BasicWebMessage;
import org.hisp.dhis.webmessage.WebResponse;

@Getter
@Accessors(chain = true)
@OpenApi.Response(status = OK, value = BasicWebMessage.class)
@OpenApi.Response(status = OK, value = WebResponse.class)
public final class HiddenNotFoundException extends Exception implements Error {
public static <E extends RuntimeException, V> V on(Class<E> type, Supplier<V> operation)
throws HiddenNotFoundException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@
import java.text.MessageFormat;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.hisp.dhis.common.OpenApi;
import org.hisp.dhis.webmessage.BasicWebMessage;
import org.hisp.dhis.common.UID;
import org.hisp.dhis.webmessage.WebResponse;

@Getter
@Accessors(chain = true)
@OpenApi.Response(status = NOT_FOUND, value = BasicWebMessage.class)
@OpenApi.Response(status = NOT_FOUND, value = WebResponse.class)
public final class NotFoundException extends Exception implements Error {
public static <E extends RuntimeException, V> V on(Class<E> type, Supplier<V> operation)
throws NotFoundException {
Expand All @@ -58,6 +60,10 @@ public NotFoundException(Class<?> type, String uid) {
this(type.getSimpleName() + " with id " + uid + " could not be found.");
}

public NotFoundException(Class<?> type, @Nonnull UID uid) {
this(type, uid.getValue());
}

public NotFoundException(String message) {
super(message);
this.code = ErrorCode.E1005;
Expand Down
11 changes: 11 additions & 0 deletions dhis-2/dhis-api/src/main/java/org/hisp/dhis/icon/IconService.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ public interface IconService {
String addDefaultIconImage(@Nonnull String key, @Nonnull DefaultIcon origin)
throws ConflictException;

/**
* A phantom default icon is an icon that exists as {@link
* org.hisp.dhis.fileresource.FileResource} but for some reason has lost its file in the store. To
* repair the icon the file is re-uploaded.
*
* @return the number of {@link DefaultIcon} {@link org.hisp.dhis.fileresource.FileResource}s that
* were repaired.
* @throws ConflictException when an exception occurred during repair
*/
int repairPhantomDefaultIcons() throws ConflictException;

/**
* Get the count of Icons based on filters provided in {@link IconQueryParams}
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ default String getGlobalShellAppName() {
*/

default boolean isEmailConfigured() {
return !getEmailHostName().isBlank() && getEmailUsername().isBlank();
return !getEmailHostName().isBlank() && !getEmailUsername().isBlank();
}

default boolean isHideUnapprovedDataInAnalytics() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
*/
@Getter
@OpenApi.Kind("WebMessageResponse")
public class BasicWebMessage {
public class WebResponse {

/**
* Message status, currently two statuses are available: OK, ERROR. Default value is OK.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@
import org.junit.jupiter.params.provider.NullAndEmptySource;

class AssignedUserQueryParamTest {
public static final String CURRENT_USER_UID = "Kj6vYde4LHh";
public static final UID CURRENT_USER_UID = UID.of("Kj6vYde4LHh");

public static final String NON_CURRENT_USER_UID = "f1AyMswryyX";
public static final UID NON_CURRENT_USER_UID = UID.of("f1AyMswryyX");

public static final Set<String> NON_CURRENT_USER_UIDS = Set.of(NON_CURRENT_USER_UID);
public static final Set<UID> NON_CURRENT_USER_UIDS = Set.of(NON_CURRENT_USER_UID);

@Test
void testUserWithAssignedUsersGivenUsersAndModeProvided() {
Expand All @@ -74,7 +74,7 @@ void testUserWithAssignedUsersGivenUsersAndNoMode() {

@ParameterizedTest
@NullAndEmptySource
void testUserWithAssignedUsersGivenNoModeAndNoUsers(Set<String> users) {
void testUserWithAssignedUsersGivenNoModeAndNoUsers(Set<UID> users) {

AssignedUserQueryParam param = new AssignedUserQueryParam(null, users, CURRENT_USER_UID);

Expand All @@ -85,7 +85,7 @@ void testUserWithAssignedUsersGivenNoModeAndNoUsers(Set<String> users) {

@ParameterizedTest
@NullAndEmptySource
void testUserWithAssignedUsersFailsGivenNoUsersAndProvided(Set<String> users) {
void testUserWithAssignedUsersFailsGivenNoUsersAndProvided(Set<UID> users) {

assertThrows(
IllegalQueryException.class,
Expand All @@ -94,7 +94,7 @@ void testUserWithAssignedUsersFailsGivenNoUsersAndProvided(Set<String> users) {

@ParameterizedTest
@NullAndEmptySource
void testUserWithAssignedUsersGivenCurrentUserAndModeCurrentAndUsersNull(Set<String> users) {
void testUserWithAssignedUsersGivenCurrentUserAndModeCurrentAndUsersNull(Set<UID> users) {
AssignedUserQueryParam param = new AssignedUserQueryParam(CURRENT, users, CURRENT_USER_UID);

assertEquals(PROVIDED, param.getMode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -124,6 +125,34 @@ public String addDefaultIconImage(@Nonnull String key, @Nonnull DefaultIcon orig
}
}

@Override
@Transactional
public int repairPhantomDefaultIcons() throws ConflictException {
int c = 0;
List<String> keys =
Stream.of(DefaultIcon.values()).flatMap(i -> i.getVariantKeys().stream()).toList();
IconQueryParams params = new IconQueryParams();
params.setPaging(false);
params.setKeys(keys);
try {
List<Icon> icons = getIcons(params);
for (Icon i : icons) {
if (!fileResourceContentStore.fileResourceContentExists(
i.getFileResource().getStorageKey())) {
try (InputStream image = getDefaultIconResource(i.getKey()).getInputStream()) {
fileResourceService.syncSaveFileResource(i.getFileResource(), image);
}
c++;
}
}
} catch (Exception ex) {
ConflictException e = new ConflictException("Repair failed");
e.initCause(ex);
throw e;
}
return c;
}

private static Resource getDefaultIconResource(String key) {
return new ClassPathResource(String.format("%s/%s.%s", ICON_PATH, key, DefaultIcon.SUFFIX));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1842,7 +1842,7 @@ attribute=Attribute
category_option=Category Option
category=\u0ea5\u0ea7\u0e87\u0e99\u0ead\u0e99
category_combo=Category Combination
category_option_combo=Category option combination
category_option_combo=\u0e81\u0eb2\u0e99\u0ea5\u0ea7\u0ea1\u0e95\u0ebb\u0ea7\u0ec0\u0ea5\u0eb7\u0ead\u0e81\u0edd\u0ea7\u0e94\u0edd\u0eb9\u0ec8
category_option_group_set=Category Option Group Set
indicator_type=Indicator Type
data_set=Data Set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1792,11 +1792,11 @@ email_invite_1_3rd_paragraph=\u4f60\u5fc5\u987b\u57283\u6708\u5185\u54cd\u5e94\u

#-- Verify email -------------------------------------------------------------#

email_verify_1_1st_paragraph_before_application_title=This is a message to verify a
email_verify_1_1st_paragraph_after_application_title=, user account email.
email_verify_1_2nd_paragraph=Please click the link below to verify the email address of your account.
email_verify_1_3rd_paragraph=You must respond to this email within one hour. If you take no action, the email address will not be verified.
verify_email_subject=Verify email address
email_verify_1_1st_paragraph_before_application_title=\u8fd9\u662f\u4e00\u6761\u6d88\u606f\u9a8c\u8bc1
email_verify_1_1st_paragraph_after_application_title=, \u7528\u6237\u5e10\u6237\u7535\u5b50\u90ae\u4ef6\u3002
email_verify_1_2nd_paragraph=\u8bf7\u70b9\u51fb\u4e0b\u9762\u7684\u94fe\u63a5\u9a8c\u8bc1\u60a8\u7684\u8d26\u6237\u7535\u5b50\u90ae\u4ef6\u5730\u5740\u3002
email_verify_1_3rd_paragraph=\u60a8\u5fc5\u987b\u5728\u4e00\u5c0f\u65f6\u5185\u56de\u590d\u6b64\u7535\u5b50\u90ae\u4ef6\u3002\u5982\u679c\u60a8\u6ca1\u6709\u91c7\u53d6\u4efb\u4f55\u884c\u52a8\uff0c\u8be5\u7535\u5b50\u90ae\u4ef6\u5730\u5740\u5c06\u65e0\u6cd5\u901a\u8fc7\u9a8c\u8bc1\u3002
verify_email_subject=\u9a8c\u8bc1\u7535\u5b50\u90ae\u4ef6\u5730\u5740

#-- Cache strategy display strings --------------------------------------------#

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
import org.hisp.dhis.feedback.Status;
import org.hisp.dhis.predictor.PredictionSummary;
import org.hisp.dhis.webapi.controller.tracker.imports.TrackerJobWebMessageResponse;
import org.hisp.dhis.webmessage.BasicWebMessage;
import org.hisp.dhis.webmessage.WebMessageResponse;
import org.hisp.dhis.webmessage.WebResponse;
import org.springframework.http.HttpStatus;

/**
Expand All @@ -72,7 +72,7 @@
"devMessage",
"response"
})
public class WebMessage extends BasicWebMessage {
public class WebMessage extends WebResponse {

/** HTTP status. */
private HttpStatus httpStatus = HttpStatus.OK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,13 @@ void testIsValid_Date() {
assertFalse(settings.isValid("keyLastMonitoringRun", "hello"));
assertFalse(settings.isValid("keyLastMonitoringRun", "true"));
}

@Test
void testEmailIsConfigured() {
SystemSettings settings = SystemSettings.of(Map.of());
assertFalse(settings.isEmailConfigured());
settings =
SystemSettings.of(Map.of("keyEmailHostName", "localhost", "keyEmailUsername", "user"));
assertTrue(settings.isEmailConfigured());
}
}
Loading

0 comments on commit 72c4f5b

Please sign in to comment.