Commit a47b8c62 authored by Martin Lowe's avatar Martin Lowe 🇨🇦
Browse files

Merge branch 'malowe/master/1.4.7' into 'master'

Malowe/master/1.4.7

See merge request !576
parents 9cca9400 9ff2fe1a
Pipeline #4360 passed with stage
in 0 seconds
......@@ -6,7 +6,7 @@
<version>1.4.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<eclipse-api-version>0.6.2-SNAPSHOT</eclipse-api-version>
<eclipse-api-version>0.6.3-SNAPSHOT</eclipse-api-version>
<surefire-plugin.version>2.22.1</surefire-plugin.version>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<maven.compiler.target>11</maven.compiler.target>
......
package org.eclipsefoundation.api;
import java.util.List;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.BeanParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
......@@ -10,6 +13,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipsefoundation.api.model.SysModLogData;
import org.eclipsefoundation.core.service.APIMiddleware.BaseAPIParameters;
import io.quarkus.oidc.client.filter.OidcClientFilter;
......@@ -24,4 +28,9 @@ public interface SysAPI {
@Path("relations")
@RolesAllowed("fdb_read_sys")
public Response getSysRelations(@BeanParam BaseAPIParameters baseParams, @QueryParam("type") String type);
@PUT
@Path("mod_logs")
@RolesAllowed("fdb_write_sys_modlog")
public List<SysModLogData> postModLog(SysModLogData modLog);
}
package org.eclipsefoundation.api.model;
import java.time.ZonedDateTime;
import java.util.Date;
import javax.annotation.Nullable;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.auto.value.AutoValue;
@AutoValue
@JsonDeserialize(builder = AutoValue_SysModLogData.Builder.class)
public abstract class SysModLogData {
@Nullable
public abstract Integer getLogID();
public abstract String getLogTable();
public abstract String getPK1();
@Nullable
public abstract String getPK2();
public abstract String getLogAction();
public abstract String getPersonId();
public abstract ZonedDateTime getModDateTime();
public static Builder builder() {
return new AutoValue_SysModLogData.Builder();
}
@AutoValue.Builder
@JsonPOJOBuilder(withPrefix = "set")
public abstract static class Builder {
public abstract Builder setLogID(@Nullable Integer logID);
public abstract Builder setLogTable(String logTable);
public abstract Builder setPK1(String pK1);
public abstract Builder setPK2(@Nullable String pK2);
public abstract Builder setLogAction(String logAction);
public abstract Builder setPersonId(String personId);
public abstract Builder setModDateTime(ZonedDateTime modDateTime);
public abstract SysModLogData build();
}
}
package org.eclipsefoundation.membership.portal.helper;
import java.sql.Date;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.eclipsefoundation.api.SysAPI;
import org.eclipsefoundation.api.model.SysModLogData;
import org.eclipsefoundation.core.service.APIMiddleware;
import org.eclipsefoundation.persistence.model.DtoTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.quarkus.security.identity.SecurityIdentity;
/**
* Helps format modlogs to be consistent and then posts them to the FoundationDB SYS API.
*
* @author Martin Lowe
*
*/
@ApplicationScoped
public class ModLogHelper {
public static final Logger LOGGER = LoggerFactory.getLogger(ModLogHelper.class);
@Inject
APIMiddleware middle;
@Inject
@RestClient
SysAPI api;
public SysModLogData postDeleteModLog(SecurityIdentity ident, DtoTable type, String pk1, String pk2) {
return postDeleteModLog(ident, type.getType().getSimpleName(), pk1, pk2);
}
public SysModLogData postUpdateModLog(SecurityIdentity ident, DtoTable type, String pk1, String pk2) {
return postUpdateModLog(ident, type.getType().getSimpleName(), pk1, pk2);
}
public SysModLogData postInsertModLog(SecurityIdentity ident, DtoTable type, String pk1, String pk2) {
return postInsertModLog(ident, type.getType().getSimpleName(), pk1, pk2);
}
public SysModLogData postDeleteModLog(SecurityIdentity ident, String type, String pk1, String pk2) {
return postModLog(ident, type, "DELETE", pk1, pk2);
}
public SysModLogData postUpdateModLog(SecurityIdentity ident, String type, String pk1, String pk2) {
return postModLog(ident, type, "UPDATE", pk1, pk2);
}
public SysModLogData postInsertModLog(SecurityIdentity ident, String type, String pk1, String pk2) {
return postModLog(ident, type, "INSERT", pk1, pk2);
}
public SysModLogData postCustomModLog(SecurityIdentity ident, String type, String pk1, String pk2, String action) {
return postModLog(ident, type, action, pk1, pk2);
}
/**
* Handles writes to the modlog for the user.
*
* @param ident the user triggering the update
* @param type the name of the table that is being updated
* @param operation the type of operation (e.g. UPDATE or DELETE)
* @param pk1 the primary key of the object that was updated
* @param pk2 optional, an additional primary key to help represent composite key objects
* @return the updated entry in foundation DB (sans logID as that is not available to the RT)
*/
private SysModLogData postModLog(SecurityIdentity ident, String type, String operation, String pk1, String pk2) {
SysModLogData data = SysModLogData.builder().setPersonId(ident.getPrincipal().getName())
.setLogAction(operation).setLogTable(type).setModDateTime(TimeHelper.now()).setPK1(pk1)
.setPK2(pk2 == null ? "" : pk2).build();
LOGGER.trace("ModLog: {}",data);
List<SysModLogData> r = api.postModLog(data);
if (r == null || r.isEmpty()) {
return null;
}
return r.get(0);
}
}
......@@ -42,6 +42,7 @@ import org.eclipsefoundation.core.model.RequestWrapper;
import org.eclipsefoundation.core.namespace.DefaultUrlParameterNames;
import org.eclipsefoundation.core.service.APIMiddleware;
import org.eclipsefoundation.core.service.CachingService;
import org.eclipsefoundation.membership.portal.helper.ModLogHelper;
import org.eclipsefoundation.membership.portal.model.EnhancedPersonData;
import org.eclipsefoundation.membership.portal.namespace.OrganizationalUserType;
import org.eclipsefoundation.membership.portal.service.OrganizationsService;
......@@ -77,6 +78,8 @@ public abstract class AbstractRESTResource {
@Inject
CSRFHelper csrfHelper;
@Inject
ModLogHelper modLogHelper;
@Inject
AdditionalUserData aud;
@Inject
SecurityIdentity ident;
......
......@@ -30,6 +30,7 @@ import org.eclipsefoundation.api.model.OrganizationContactData;
import org.eclipsefoundation.api.model.PeopleData;
import org.eclipsefoundation.api.model.SysRelationData;
import org.eclipsefoundation.core.namespace.RequestHeaderNames;
import org.eclipsefoundation.eclipsedb.dto.OrganizationInformation;
import org.eclipsefoundation.membership.portal.model.ContactRemovalRequestData;
import org.eclipsefoundation.membership.portal.model.EnhancedPersonData;
import org.eclipsefoundation.membership.portal.model.MemberOrganization;
......@@ -37,6 +38,7 @@ import org.eclipsefoundation.membership.portal.namespace.OrganizationalUserType;
import org.eclipsefoundation.membership.portal.request.RolesAllowed;
import org.eclipsefoundation.membership.portal.request.model.ContactRemovalRequest;
import org.eclipsefoundation.membership.portal.service.MailerService;
import org.eclipsefoundation.persistence.model.DtoTable;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import io.quarkus.security.Authenticated;
......@@ -159,6 +161,7 @@ public class OrganizationContactsResource extends AbstractRESTResource {
// update the entity and return
orgService.updateOrganizationContact(organizationID, contact);
modLogHelper.postUpdateModLog(ident, "OrganizationContact", username.toLowerCase(), organizationID + "|" + relation);
return Response.ok().build();
}
......@@ -189,6 +192,7 @@ public class OrganizationContactsResource extends AbstractRESTResource {
}
orgService.removeOrganizationContact(organizationID, username, relation);
modLogHelper.postDeleteModLog(ident, "OrganizationContact", username.toLowerCase(), organizationID + "|" + relation);
return Response.ok().build();
}
......
......@@ -120,7 +120,7 @@ public class OrganizationResource extends AbstractRESTResource {
return Response.ok(Collections.emptyList()).build();
}
wrap.setParam(FoundationDBParameterNames.DOCUMENT_IDS.getName(), docids);
} else if(wg == null && StringUtils.isNotBlank(workingGroup)) {
} else if (wg == null && StringUtils.isNotBlank(workingGroup)) {
// return empty response if wg was set but no results
return Response.ok(Collections.emptyList()).build();
}
......@@ -179,6 +179,7 @@ public class OrganizationResource extends AbstractRESTResource {
if (org.isEmpty()) {
return Response.status(503).build();
}
modLogHelper.postUpdateModLog(ident, OrganizationInformation.TABLE, organizationID, null);
return Response.ok(org.get()).build();
}
......@@ -348,6 +349,10 @@ public class OrganizationResource extends AbstractRESTResource {
if (orgProducts.isEmpty()) {
return Response.ok(Collections.emptyList()).build();
}
// track creation/update of product
Integer pId = orgProducts.get(0).getCompositeId().getProductId();
modLogHelper.postInsertModLog(ident, OrganizationProducts.TABLE, organizationID,
pId != null ? Integer.toString(pId) : null);
return Response.noContent().build();
}
......@@ -379,6 +384,9 @@ public class OrganizationResource extends AbstractRESTResource {
if (orgProducts.isEmpty()) {
return Response.ok(Collections.emptyList()).build();
}
// track creation/update of product
modLogHelper.postUpdateModLog(ident, OrganizationProducts.TABLE, Integer.toString(organizationID),
Integer.toString(productID));
return Response.ok(productMapper.toModel(orgProducts.get(0))).build();
}
......@@ -392,6 +400,7 @@ public class OrganizationResource extends AbstractRESTResource {
params.add(EclipseDBParameterNames.ORGANIZATION_ID.getName(), organizationID);
params.add(EclipseDBParameterNames.PRODUCT_ID.getName(), productID);
eclipseDBDao.delete(new RDBMSQuery<>(wrap, filters.get(OrganizationProducts.class), params));
modLogHelper.postDeleteModLog(ident, OrganizationProducts.TABLE, organizationID, productID);
return Response.ok().build();
}
......@@ -443,6 +452,7 @@ public class OrganizationResource extends AbstractRESTResource {
if (org.isEmpty()) {
return Response.status(404).build();
}
modLogHelper.postUpdateModLog(ident, OrganizationInformation.TABLE, organizationID, format.getName());
return Response.ok(org.get()).build();
}
......
......@@ -56,6 +56,8 @@ import org.eclipsefoundation.membership.portal.model.MemberOrganization.MemberOr
import org.eclipsefoundation.membership.portal.model.MemberOrganization.MemberOrganizationLevel;
import org.eclipsefoundation.membership.portal.model.MemberOrganization.MemberOrganizationLogos;
import org.eclipsefoundation.membership.portal.model.MemberOrganization.OrganizationWGPA;
import org.eclipsefoundation.membership.portal.model.WorkingGroupMap.WorkingGroup;
import org.eclipsefoundation.membership.portal.model.WorkingGroupMap.WorkingGroupParticipationLevel;
import org.eclipsefoundation.membership.portal.namespace.ImageStoreFormat.ImageStoreFormats;
import org.eclipsefoundation.membership.portal.namespace.MembershipFormAPIParameterNames;
import org.eclipsefoundation.membership.portal.namespace.OrganizationalUserType;
......@@ -446,9 +448,17 @@ public class FoundationDBOrganizationService implements OrganizationsService {
// find the first entry that has a matching ID for current document
Optional<Entry<String, List<String>>> wgID = wgpaDocIDs.entrySet().stream()
.filter(e -> e.getValue().contains(wgpa.getDocumentId())).findFirst();
// if this is missing then we have a document that wasn't in the list of IDs passed to fetch
owgpa.setWorkingGroup(wgID.isPresent() ? wgID.get().getKey() : "unknown");
// if this is missing then we have a document that wasn't id'd as a WGPA doc
if (wgID.isPresent()) {
// should always be present as the alias comes from an existing group
WorkingGroup wg = wgService.getByName(wgID.get().getKey());
Optional<WorkingGroupParticipationLevel> pl = wg.getLevels().stream()
.filter(l -> l.getRelation().equals(wgpa.getRelation())).findFirst();
pl.ifPresent(wgpl -> owgpa.setDescription(wgpl.getDescription()));
owgpa.setWorkingGroup(wg.getAlias());
} else {
owgpa.setWorkingGroup("unknown");
}
return owgpa.build();
}).collect(Collectors.toList()));
return out.build();
......
......@@ -722,8 +722,8 @@
"pdf": "https://www.eclipse.org/org/workinggroups/wgpa/openhw-asia-working-group-participation-agreement.pdf"
}
},
"website": "",
"members": "",
"website": "https://www.openhwgroup.org/working-groups/openhw-asia/",
"members": "https://www.openhwgroup.org/working-groups/openhw-asia/#members",
"sponsorship": "",
"contact_form": "https://accounts.eclipse.org/contact/membership"
},
......@@ -754,8 +754,8 @@
"pdf": "https://www.eclipse.org/org/workinggroups/wgpa/openhw-europe-working-group-participation-agreement.pdf"
}
},
"website": "",
"members": "",
"website": "https://www.openhwgroup.org/working-groups/openhw-europe/",
"members": "https://www.openhwgroup.org/working-groups/openhw-europe/#members",
"sponsorship": "",
"contact_form": "https://accounts.eclipse.org/contact/membership",
"membership": ""
......
......@@ -10,6 +10,7 @@ import javax.ws.rs.core.Response;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.eclipsefoundation.api.SysAPI;
import org.eclipsefoundation.api.model.SysModLogData;
import org.eclipsefoundation.api.model.SysRelationData;
import org.eclipsefoundation.core.service.APIMiddleware.BaseAPIParameters;
......@@ -77,8 +78,12 @@ public class MockSysAPI implements SysAPI {
@Override
public Response getSysRelations(BaseAPIParameters baseParams, String type) {
// TODO Auto-generated method stub
return Response.ok(relations).build();
}
@Override
public List<SysModLogData> postModLog(SysModLogData modLog) {
return Arrays.asList(modLog);
}
}
......@@ -6,34 +6,10 @@ export default function AppFooter() {
return (
<div>
{/* Sign Up to our Newsletter */}
<div
className="featured-footer featured-footer-newsletter"
style={{
backgroundSize: 'cover',
backgroundImage:
'url(https://eclipse.org/home/images/eclipse-ide-2020-03.jpg)',
borderBottom: '1px solid #ccc',
borderTop: '1px solid #ccc',
backgroundPosition: 'bottom',
}}
>
<div className="eclipsefdn-featured-story featured-footer featured-story-light" data-publish-target="eclipse_org">
<div className="container">
<div className="row">
<div className="col-sm-24">
<h2 className="margin-top-30">
<strong>Join us for EclipseCon 2020</strong>
</h2>
<p>
EclipseCon 2020 is a free virtual event for the Eclipse
community. Join us October 19-22!
</p>
<a
className="btn btn-primary btn-lg"
href="https://www.eclipsecon.org/2020/registration"
>
Register Now
</a>
</div>
<div className="col-sm-24 featured-container"></div>
</div>
</div>
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment