|
18 | 18 |
|
19 | 19 | package org.wso2.carbon.identity.api.server.application.management.v1.core; |
20 | 20 |
|
21 | | -import com.fasterxml.jackson.core.JsonFactory; |
22 | | -import com.fasterxml.jackson.core.JsonProcessingException; |
23 | | -import com.fasterxml.jackson.databind.ObjectMapper; |
24 | 21 | import org.apache.commons.collections.CollectionUtils; |
25 | 22 | import org.apache.commons.io.IOUtils; |
26 | 23 | import org.apache.commons.lang.ArrayUtils; |
|
91 | 88 | import org.wso2.carbon.identity.api.server.common.ContextLoader; |
92 | 89 | import org.wso2.carbon.identity.api.server.common.Util; |
93 | 90 | import org.wso2.carbon.identity.api.server.common.error.APIError; |
| 91 | +import org.wso2.carbon.identity.api.server.common.file.FileContent; |
| 92 | +import org.wso2.carbon.identity.api.server.common.file.FileSerializationConfig; |
| 93 | +import org.wso2.carbon.identity.api.server.common.file.FileSerializationException; |
| 94 | +import org.wso2.carbon.identity.api.server.common.file.FileSerializationUtil; |
| 95 | +import org.wso2.carbon.identity.api.server.common.file.JsonConfig; |
| 96 | +import org.wso2.carbon.identity.api.server.common.file.XmlConfig; |
| 97 | +import org.wso2.carbon.identity.api.server.common.file.YamlConfig; |
94 | 98 | import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants; |
95 | 99 | import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants.StandardInboundProtocols; |
96 | 100 | import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException; |
|
147 | 151 | import org.wso2.carbon.identity.template.mgt.model.Template; |
148 | 152 | import org.wso2.carbon.user.core.common.AbstractUserStoreManager; |
149 | 153 | import org.wso2.carbon.user.core.service.RealmService; |
150 | | -import org.yaml.snakeyaml.DumperOptions; |
151 | | -import org.yaml.snakeyaml.LoaderOptions; |
152 | 154 | import org.yaml.snakeyaml.TypeDescription; |
153 | | -import org.yaml.snakeyaml.Yaml; |
154 | | -import org.yaml.snakeyaml.constructor.Constructor; |
155 | | -import org.yaml.snakeyaml.error.YAMLException; |
156 | | -import org.yaml.snakeyaml.inspector.TagInspector; |
157 | | -import org.yaml.snakeyaml.inspector.TrustedPrefixesTagInspector; |
158 | 155 |
|
159 | 156 | import java.io.IOException; |
160 | 157 | import java.io.InputStream; |
161 | | -import java.io.StringReader; |
162 | | -import java.io.StringWriter; |
163 | 158 | import java.net.MalformedURLException; |
164 | 159 | import java.net.URISyntaxException; |
165 | 160 | import java.net.URL; |
|
179 | 174 |
|
180 | 175 | import javax.activation.MimeType; |
181 | 176 | import javax.activation.MimeTypeParseException; |
182 | | -import javax.xml.bind.JAXBContext; |
183 | | -import javax.xml.bind.JAXBException; |
184 | 177 | import javax.xml.bind.Marshaller; |
185 | | -import javax.xml.bind.Unmarshaller; |
186 | 178 |
|
187 | 179 | import static org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementConstants.ADVANCED_CONFIGURATIONS; |
188 | 180 | import static org.wso2.carbon.identity.api.server.application.management.common.ApplicationManagementConstants.APPLICATION_BASED_OUTBOUND_PROVISIONING_ENABLED; |
@@ -267,6 +259,8 @@ public ServerApplicationManagementService(ApplicationManagementService applicati |
267 | 259 | private static final String[] VALID_MEDIA_TYPES_JSON = {"application/json", "text/json"}; |
268 | 260 | private static final Class<?>[] INBOUND_CONFIG_PROTOCOLS = new Class<?>[]{ServiceProvider.class, |
269 | 261 | SAMLSSOServiceProviderDTO.class, OAuthAppDO.class}; |
| 262 | + private static final Class<?>[] ADDITIONAL_INBOUND_CONFIG_PROTOCOLS = new Class<?>[]{ |
| 263 | + SAMLSSOServiceProviderDTO.class, OAuthAppDO.class}; |
270 | 264 |
|
271 | 265 | static { |
272 | 266 | SUPPORTED_FILTER_ATTRIBUTES.add(NAME); |
@@ -586,90 +580,64 @@ private TransferResource generateFileFromModel(String fileType, ServiceProvider |
586 | 580 | log.debug("Generating file content from model for application: " + serviceProvider.getApplicationName()); |
587 | 581 | } |
588 | 582 |
|
589 | | - StringBuilder fileNameSB = new StringBuilder(serviceProvider.getApplicationName()); |
590 | | - String fileContent; |
591 | | - |
592 | | - if (Arrays.asList(VALID_MEDIA_TYPES_XML).contains(fileType)) { |
593 | | - fileContent = parseXmlFromServiceProvider(serviceProvider); |
594 | | - fileNameSB.append(XML_FILE_EXTENSION); |
595 | | - } else if (Arrays.asList(VALID_MEDIA_TYPES_YAML).contains(fileType)) { |
596 | | - fileContent = parseYamlFromServiceProvider(serviceProvider); |
597 | | - fileNameSB.append(YML_FILE_EXTENSION); |
598 | | - } else if (Arrays.asList(VALID_MEDIA_TYPES_JSON).contains(fileType)) { |
599 | | - fileContent = parseJsonFromServiceProvider(serviceProvider); |
600 | | - fileNameSB.append(JSON_FILE_EXTENSION); |
601 | | - } else { |
602 | | - throw Utils.buildServerError("Unsupported media type: " + fileType + "." |
603 | | - + " Supported media types are " + Arrays.toString(VALID_MEDIA_TYPES_XML) + ", " |
604 | | - + Arrays.toString(VALID_MEDIA_TYPES_YAML) + ", " + Arrays.toString(VALID_MEDIA_TYPES_JSON)); |
605 | | - } |
606 | | - |
607 | 583 | try { |
| 584 | + FileContent fileContent = |
| 585 | + FileSerializationUtil.serialize( |
| 586 | + serviceProvider, |
| 587 | + serviceProvider.getApplicationName(), |
| 588 | + fileType, |
| 589 | + buildSerializationConfig() |
| 590 | + ); |
| 591 | + |
608 | 592 | return new TransferResource( |
609 | | - fileNameSB.toString(), |
610 | | - fileContent.getBytes(StandardCharsets.UTF_8), |
| 593 | + fileContent.getFileName(), |
| 594 | + fileContent.getContent().getBytes(StandardCharsets.UTF_8), |
611 | 595 | new MimeType("application/octet-stream") |
612 | 596 | ); |
| 597 | + } catch (FileSerializationException e) { |
| 598 | + throw Utils.buildServerError("Error exporting application from file.", e); |
613 | 599 | } catch (MimeTypeParseException e) { |
614 | 600 | throw new RuntimeException("Failed to parse MIME type", e); |
615 | 601 | } |
616 | 602 | } |
617 | 603 |
|
618 | | - private String parseXmlFromServiceProvider(ServiceProvider serviceProvider) { |
| 604 | + private FileSerializationConfig buildSerializationConfig() { |
619 | 605 |
|
620 | | - JAXBContext jaxbContext; |
621 | | - try { |
622 | | - jaxbContext = JAXBContext.newInstance(INBOUND_CONFIG_PROTOCOLS); |
623 | | - Marshaller marshaller = jaxbContext.createMarshaller(); |
624 | | - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); |
| 606 | + FileSerializationConfig config = new FileSerializationConfig(); |
| 607 | + |
| 608 | + XmlConfig xmlConfig = new XmlConfig(); |
| 609 | + xmlConfig.setAdditionalJaxbClasses(ADDITIONAL_INBOUND_CONFIG_PROTOCOLS); |
| 610 | + xmlConfig.setMarshallerCustomizer(marshaller -> { |
625 | 611 | marshaller.setListener(new Marshaller.Listener() { |
626 | 612 | @Override |
627 | 613 | public void beforeMarshal(Object source) { |
628 | 614 | if (source instanceof InboundAuthenticationConfig) { |
629 | | - InboundAuthenticationConfig config = (InboundAuthenticationConfig) source; |
| 615 | + InboundAuthenticationConfig authConfig = (InboundAuthenticationConfig) source; |
630 | 616 | for (InboundAuthenticationRequestConfig requestConfig |
631 | | - : config.getInboundAuthenticationRequestConfigs()) { |
| 617 | + : authConfig.getInboundAuthenticationRequestConfigs()) { |
632 | 618 | requestConfig.setInboundConfiguration(null); |
633 | 619 | } |
634 | 620 | } |
635 | 621 | } |
636 | 622 | }); |
637 | | - StringWriter stringWriter = new StringWriter(); |
638 | | - marshaller.marshal(serviceProvider, stringWriter); |
639 | | - return stringWriter.toString(); |
640 | | - } catch (JAXBException e) { |
641 | | - throw Utils.buildServerError("Error exporting application from XML file.", e); |
642 | | - } |
643 | | - } |
644 | | - |
645 | | - private String parseYamlFromServiceProvider(ServiceProvider serviceProvider) { |
| 623 | + }); |
| 624 | + config.setXmlConfig(xmlConfig); |
646 | 625 |
|
647 | | - Constructor constructor = new Constructor(new LoaderOptions()); |
648 | | - CustomRepresenter representer = new CustomRepresenter(new DumperOptions()); |
649 | | - |
650 | | - for (Class<?> protocol : INBOUND_CONFIG_PROTOCOLS) { |
651 | | - TypeDescription description = new TypeDescription(InboundConfigurationProtocol.class); |
652 | | - description.addPropertyParameters("type", protocol); |
653 | | - constructor.addTypeDescription(description); |
654 | | - } |
655 | | - |
656 | | - Yaml yaml = new Yaml(constructor, representer); |
657 | | - try { |
658 | | - return yaml.dump(serviceProvider); |
659 | | - } catch (YAMLException e) { |
660 | | - throw Utils.buildServerError("Error exporting application from YAML file.", e); |
661 | | - } |
662 | | - } |
| 626 | + YamlConfig yamlConfig = new YamlConfig(); |
| 627 | + yamlConfig.setConstructorCustomizer(constructor -> { |
| 628 | + for (Class<?> protocol : INBOUND_CONFIG_PROTOCOLS) { |
| 629 | + TypeDescription description = new TypeDescription(InboundConfigurationProtocol.class); |
| 630 | + description.addPropertyParameters("type", protocol); |
| 631 | + constructor.addTypeDescription(description); |
| 632 | + } |
| 633 | + }); |
| 634 | + config.setYamlConfig(yamlConfig); |
663 | 635 |
|
664 | | - private String parseJsonFromServiceProvider(ServiceProvider serviceProvider) { |
| 636 | + JsonConfig jsonConfig = new JsonConfig(); |
| 637 | + jsonConfig.setSubtypes(INBOUND_CONFIG_PROTOCOLS); |
| 638 | + config.setJsonConfig(jsonConfig); |
665 | 639 |
|
666 | | - ObjectMapper objectMapper = new ObjectMapper(new JsonFactory()); |
667 | | - objectMapper.registerSubtypes(INBOUND_CONFIG_PROTOCOLS); |
668 | | - try { |
669 | | - return objectMapper.writeValueAsString(serviceProvider); |
670 | | - } catch (JsonProcessingException e) { |
671 | | - throw Utils.buildServerError("Error exporting application from JSON file.", e); |
672 | | - } |
| 640 | + return config; |
673 | 641 | } |
674 | 642 |
|
675 | 643 | /** |
@@ -758,74 +726,42 @@ private ServiceProvider parseSP(SpFileContent spFileContent, String fileType, St |
758 | 726 | spFileContent.getFileName(), tenantDomain)); |
759 | 727 | } |
760 | 728 |
|
761 | | - if (containsValidMediaType(fileType, VALID_MEDIA_TYPES_XML)) { |
762 | | - return parseServiceProviderFromXml(spFileContent, tenantDomain); |
763 | | - } else if (containsValidMediaType(fileType, VALID_MEDIA_TYPES_YAML)) { |
764 | | - return parseServiceProviderFromYaml(spFileContent, tenantDomain); |
765 | | - } else if (containsValidMediaType(fileType, VALID_MEDIA_TYPES_JSON)) { |
766 | | - return parseServiceProviderFromJson(spFileContent, tenantDomain); |
767 | | - } else { |
768 | | - log.warn("Unsupported file type " + fileType + " for file " + spFileContent.getFileName() + " . " + |
769 | | - "Defaulting to XML parsing"); |
770 | | - return parseServiceProviderFromXml(spFileContent, tenantDomain); |
771 | | - } |
772 | | - } |
773 | | - |
774 | | - private boolean containsValidMediaType(String fileType, String[] mediaTypes) { |
775 | | - |
776 | | - for (String mediaType : mediaTypes) { |
777 | | - if (fileType.contains(mediaType)) { |
778 | | - return true; |
779 | | - } |
780 | | - } |
781 | | - return false; |
782 | | - } |
783 | | - |
784 | | - private ServiceProvider parseServiceProviderFromXml(SpFileContent spFileContent, String tenantDomain) |
785 | | - throws IdentityApplicationManagementException { |
786 | | - |
787 | 729 | try { |
788 | | - JAXBContext jaxbContext = JAXBContext.newInstance(INBOUND_CONFIG_PROTOCOLS); |
789 | | - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); |
790 | | - return (ServiceProvider) unmarshaller.unmarshal(new StringReader(spFileContent.getContent())); |
791 | | - } catch (JAXBException e) { |
792 | | - throw new IdentityApplicationManagementException(String.format("Error in reading XML Service Provider " + |
| 730 | + FileContent fileContent = |
| 731 | + new FileContent( |
| 732 | + spFileContent.getFileName(), |
| 733 | + fileType, |
| 734 | + spFileContent.getContent() |
| 735 | + ); |
| 736 | + |
| 737 | + return FileSerializationUtil.deserialize( |
| 738 | + fileContent, |
| 739 | + ServiceProvider.class, |
| 740 | + buildDeserializationConfig() |
| 741 | + ); |
| 742 | + } catch (FileSerializationException e) { |
| 743 | + throw new IdentityApplicationManagementException(String.format("Error in reading Service Provider " + |
793 | 744 | "configuration file %s uploaded by tenant: %s", spFileContent.getFileName(), tenantDomain), e); |
794 | 745 | } |
795 | 746 | } |
796 | 747 |
|
797 | | - private ServiceProvider parseServiceProviderFromYaml(SpFileContent spFileContent, String tenantDomain) |
798 | | - throws IdentityApplicationManagementException { |
| 748 | + private FileSerializationConfig buildDeserializationConfig() { |
799 | 749 |
|
800 | | - try { |
801 | | - // Add trusted tags included in the SP YAML file. |
802 | | - List<String> trustedTagList = new ArrayList<>(); |
803 | | - trustedTagList.add(ServiceProvider.class.getName()); |
804 | | - trustedTagList.add(OAuthAppDO.class.getName()); |
805 | | - trustedTagList.add(SAMLSSOServiceProviderDTO.class.getName()); |
806 | | - |
807 | | - LoaderOptions loaderOptions = new LoaderOptions(); |
808 | | - TagInspector tagInspector = new TrustedPrefixesTagInspector(trustedTagList); |
809 | | - loaderOptions.setTagInspector(tagInspector); |
810 | | - Yaml yaml = new Yaml(new Constructor(ServiceProvider.class, loaderOptions)); |
811 | | - return yaml.loadAs(spFileContent.getContent(), ServiceProvider.class); |
812 | | - } catch (YAMLException e) { |
813 | | - throw new IdentityApplicationManagementException(String.format("Error in reading YAML Service Provider " + |
814 | | - "configuration file %s uploaded by tenant: %s", spFileContent.getFileName(), tenantDomain), e); |
815 | | - } |
816 | | - } |
| 750 | + FileSerializationConfig config = new FileSerializationConfig(); |
817 | 751 |
|
818 | | - private ServiceProvider parseServiceProviderFromJson(SpFileContent spFileContent, String tenantDomain) |
819 | | - throws IdentityApplicationManagementException { |
| 752 | + XmlConfig xmlConfig = new XmlConfig(); |
| 753 | + xmlConfig.setAdditionalJaxbClasses(ADDITIONAL_INBOUND_CONFIG_PROTOCOLS); |
| 754 | + config.setXmlConfig(xmlConfig); |
820 | 755 |
|
821 | | - try { |
822 | | - ObjectMapper objectMapper = new ObjectMapper(); |
823 | | - objectMapper.registerSubtypes(INBOUND_CONFIG_PROTOCOLS); |
824 | | - return objectMapper.readValue(spFileContent.getContent(), ServiceProvider.class); |
825 | | - } catch (JsonProcessingException e) { |
826 | | - throw new IdentityApplicationManagementException(String.format("Error in reading JSON Service Provider " + |
827 | | - "configuration file %s uploaded by tenant: %s", spFileContent.getFileName(), tenantDomain), e); |
828 | | - } |
| 756 | + YamlConfig yamlConfig = new YamlConfig(); |
| 757 | + yamlConfig.setAdditionalTrustedClasses(OAuthAppDO.class, SAMLSSOServiceProviderDTO.class); |
| 758 | + config.setYamlConfig(yamlConfig); |
| 759 | + |
| 760 | + JsonConfig jsonConfig = new JsonConfig(); |
| 761 | + jsonConfig.setSubtypes(INBOUND_CONFIG_PROTOCOLS); |
| 762 | + config.setJsonConfig(jsonConfig); |
| 763 | + |
| 764 | + return config; |
829 | 765 | } |
830 | 766 |
|
831 | 767 | private SpFileContent buildSpFileContent(InputStream fileInputStream, Attachment fileDetail) throws IOException { |
|
0 commit comments