incodehq / incode-platform Goto Github PK
View Code? Open in Web Editor NEWCombines incode.org modules and isisaddons.org into a single set of modules.
Home Page: http://platform.incode.org
License: Apache License 2.0
Combines incode.org modules and isisaddons.org into a single set of modules.
Home Page: http://platform.incode.org
License: Apache License 2.0
(from Johan.... he has an implementation that he's found, in also including text, ie a "combi" reduces the chance of spam... as per mail headers).
from isisaddons-legacy/isis-wicket-fullcalendar2#1
The current implementation only supports instants (i.e. a single point in time). This is great for events like due dates of todo items. It should also provide an interface to visualize timespans (like for appointments).
e.g.
via start (datetime) + end (datetime)
or start (datetime) + duration
from isisaddons-legacy/isis-wicket-gmap3#11
You need to visualize the route traveled by a vehicle in a given time, using the map of Gmap3.
Data were obtained from a database, which will be loaded from a webservice with access to the database.
NB: initial PR provided ... isisaddons-legacy/isis-wicket-gmap3#12
Currently commented out, because the AppManifests that each reference are incomplete, basically.
from isisaddons-legacy/isis-module-excel#20
Pretty sure this is because ExcelFixture2 (and maybe ExcelFixture)'s value semantics is broken.
If if try to run the same subclass of ExcelFixture2 more than once, then this code in FixtureScript.java
//region > shouldExecute
private boolean shouldExecute(final FixtureScript fixtureScript) {
final boolean previouslyExecuted = this.previouslyExecuted.contains(fixtureScript);
if(!previouslyExecuted) {
this.previouslyExecuted.add(fixtureScript);
}
will fail, because of the "contains" call is gonna call getBytes() on the candidate fixture script which will in turn return null because the fixture script hasn't been run (we're trying to figure out at this stage whether to run the fixture script).
from isisaddons-legacy/isis-module-security#46
bilgin:
What is the reason for SecurityModuleAppUserRegistrationServiceAbstract to have 2 abstract methods getInitialRole and getAdditionalInitialRoles?
Why not have only one method that returns Set? It will be easier to override. Otherwise, it makes you think that initial role is different that any any additional role.?
per Vladimir on [email protected] (http://markmail.org/message/e7tacn3lxuej4hfj)
In a world of collaboration systems there could be an interesting extension
to your incode-module-note feature, the capability not only to add the
notes to an entity, but also to add infinite comments to that note (in
other words to add the comment threads to the entity). In combination with
text search capability (idea #1) I thinks we could build really great
features.
Text search is https://issues.apache.org/jira/browse/ISIS-383
public static Logger LOG = LoggerFactory.getLogger(SimpleModuleIntegTestAbstract.class);
public static class LoggingRule implements MethodRule {
@Override
public Statement apply(
final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
return new Statement() {
public void evaluate() throws Throwable {
log("start");
try {
statement.evaluate();
} catch (final Throwable ex) {
log("exception");
throw ex;
} finally {
log("done");
}
}
void log(final String suffix) {
LOG.info(String.format(
"%s#%s: %s",
frameworkMethod.getDeclaringClass().getName(),
frameworkMethod.getMethod().getName(),
suffix));
}
};
}
}
@Rule
public LoggingRule loggingRule = new LoggingRule();
from isisaddons-legacy/isis-module-security#43
Needs to respect the featureType, ie will be multiple actions with only one visible dependent on the type (package, class, action, property, collection)
from isisaddons-legacy/isis-module-security#48
As introduced in 1.13.2
I tried to implement this at the generic Shiro security mechanism (within Isis core), but realized that actually it needs to be at a deeper level, ie in this module.
The code I sketched out before abandoning was:
@DomainService(nature = NatureOfService.DOMAIN)
public class SudoServiceSpi implements SudoService.Spi {
@Override
public void runAs(final String username, final List<String> roles) {
try {
final Subject subject = SecurityUtils.getSubject();
if (subject == null) {
return;
}
// can't set runAs if has no current principals
if(!hasPrincipals(subject)) {
return;
}
final SimplePrincipalCollection principals = new SimplePrincipalCollection();
principals.add(new RunAsPrincipal(username, roles), "sudoRealm");
subject.runAs(principals);
} catch(UnavailableSecurityManagerException ex) {
return;
}
}
private boolean hasPrincipals(final Subject subject) {
return !CollectionUtils.isEmpty(subject.getPrincipals());
}
@Override
public void releaseRunAs() {
try {
final Subject subject = SecurityUtils.getSubject();
if(subject == null) {
return;
}
// can't set runAs if has no current principals
if(!hasPrincipals(subject) || !subject.isRunAs()) {
return;
}
subject.releaseRunAs();
} catch (UnavailableSecurityManagerException ex) {
return;
}
}
}
and also:
public class RunAsPrincipal implements AuthorizationInfo {
private final String username;
private final List<String> roles;
public RunAsPrincipal(final String username, final List<String> roles) {
this.username = username;
this.roles = roles;
}
@Override
public Collection<String> getRoles() {
return roles;
}
@Override
public Collection<String> getStringPermissions() {
return Collections.emptyList();
}
@Override
public Collection<Permission> getObjectPermissions() {
return Collections.emptyList();
}
}
Certainly RunAsPrincipal won't be needed; instead use the PrincipalForApplicationUser
that already exists.
Also, will need to decide what to do if the specified user doesn't exist in the user; perhaps fall back on the above generic code (meaning no permissions, of course).
from isisaddons-legacy/isis-module-excel#14
niv0:
The values are not coreclty imported to ..Import object.
for the "applicableToDomainType
select * from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME LIKE '%class%' or COLUMN_NAME like 'fully%' or COLUMN_NAME like '%fq%' or COLUMN_NAME like '%domainType%'
order by COLUMN_NAME, TABLE_NAME
which gives us:
incodeDocuments Applicability attachmentAdvisorClassName
dbo Link className
incodeDocuments Applicability domainClassName
incodeClassification Applicability domainType
isissecurity ApplicationPermission featureFqn
dbo FixedAssetRegistrationType fullyQualifiedClassName
incodeClassification Category fullyQualifiedName
incodeDocuments RenderingStrategy rendererClassName
incodeDocuments Applicability rendererModelFactoryClassName
for the "applicableToDomainType"
select * from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME LIKE '%class%' or COLUMN_NAME like 'fully%' or COLUMN_NAME like '%fq%' or COLUMN_NAME like '%domainType%'
order by COLUMN_NAME, TABLE_NAME
which gives us:
incodeDocuments Applicability attachmentAdvisorClassName
dbo Link className
incodeDocuments Applicability domainClassName
incodeClassification Applicability domainType
isissecurity ApplicationPermission featureFqn
dbo FixedAssetRegistrationType fullyQualifiedClassName
incodeClassification Category fullyQualifiedName
incodeDocuments RenderingStrategy rendererClassName
incodeDocuments Applicability rendererModelFactoryClassName
This is the test report --
Tests run: 2, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.021 sec <<< FAILURE! - in domainapp.modules.simple.integtests.tests.SimpleObjectMenu_IntegTest$ListAll
happyCase(domainapp.modules.simple.integtests.tests.SimpleObjectMenu_IntegTest$ListAll) Time elapsed: 0.007 sec <<< ERROR!
java.lang.NoSuchMethodError: org.apache.isis.applib.services.repository.RepositoryService.persist(Ljava/lang/Object;)V
at domainapp.modules.simple.integtests.tests.SimpleObjectMenu_IntegTest$ListAll.happyCase(SimpleObjectMenu_IntegTest.java:43)
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 4.782 sec <<< FAILURE! - in domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$DataNucleusId
should_be_populated(domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$DataNucleusId) Time elapsed: 0.034 sec <<< ERROR!
java.lang.NoSuchMethodError: org.apache.isis.applib.services.repository.RepositoryService.persist(Ljava/lang/Object;)V
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0 sec <<< FAILURE! - in domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$DataNucleusVersionTimestamp
should_be_populated(domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$DataNucleusVersionTimestamp) Time elapsed: 0 sec <<< ERROR!
java.lang.NoSuchMethodError: org.apache.isis.applib.services.repository.RepositoryService.persist(Ljava/lang/Object;)V
Tests run: 2, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 0 sec <<< FAILURE! - in domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$Name
accessible(domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$Name) Time elapsed: 0 sec <<< ERROR!
java.lang.NoSuchMethodError: org.apache.isis.applib.services.repository.RepositoryService.persist(Ljava/lang/Object;)V
not_editable(domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$Name) Time elapsed: 0 sec <<< ERROR!
java.lang.NoSuchMethodError: org.apache.isis.applib.services.repository.RepositoryService.persist(Ljava/lang/Object;)V
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0 sec <<< FAILURE! - in domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$Title
interpolatesName(domainapp.modules.simple.integtests.tests.SimpleObject_IntegTest$Title) Time elapsed: 0 sec <<< ERROR!
"tests.txt" 53L, 4999C
from isisaddons-legacy/isis-wicket-excel#4
introduce this into Isis applib:
public interface Mapper<S,T> {
```
Class<? extends S> getSourceClass();
Class<? extends T> getTargetClass();
@Programmatic
T map(S s);
```
}
Then search for domain classes that implement:
@DomainService(nature=DOMAIN)
public CountryToDto implements Mapper<Country, CountryDto> {
public CountryDto map(Country c) { ... }
}
@DomainService(nature=DOMAIN)
public CountryToRowHandler implements Mapper<Country, CountryRowHandler> {
public CountryRowHandler map(Country c) { ... }
}
and provide a drop-down selector to choose how to export (as Country, as CountryDto, as CountryRowHandler etc).
```
```
from isisaddons-legacy/isis-module-security#34
Default names of tables and foreign keys are incompatible with Oracle 11 - since some of them are longer then 30 characters.
This constraint can be solved by externalizing the package.jdo file and adaptin it, but in the e.g. ApplicationPermission class the index name is simply too long:
@javax.jdo.annotations.Uniques({@javax.jdo.annotations.Unique(name = "ApplicationPermission_role_feature_rule_UNQ", members = {"role", "featureType", "featureFqn", "rule"})})
In total there are 7 indexes with too long names.
(was EST-1174)
from isisaddons-legacy/isis-wicket-wickedcharts#2
With the current Java Math demo data in the KitchenSink application trying to show a summarychart
leads to the following exception:
Caused by: java.lang.NullPointerException
at java.math.BigDecimal.compareTo(BigDecimal.java:2554)
at java.math.BigDecimal.min(BigDecimal.java:2665)
at org.isisaddons.wicket.wickedcharts.cpt.ui.summarychart.CollectionContentsAsSummaryChart.minOf(CollectionContentsAsSummaryChart.java:163)
at org.isisaddons.wicket.wickedcharts.cpt.ui.summarychart.CollectionContentsAsSummaryChart.createChartValue(CollectionContentsAsSummaryChart.java:119)
at org.isisaddons.wicket.wickedcharts.cpt.ui.summarychart.CollectionContentsAsSummaryChart.buildGui(CollectionContentsAsSummaryChart.java:101)
at org.isisaddons.wicket.wickedcharts.cpt.ui.summarychart.CollectionContentsAsSummaryChart.onModelChanged(CollectionContentsAsSummaryChart.java:168)
Failed integration tests:
CommunicationChannelOwner_addPostalAddress_IntegTest$ActionImplementationIntegrationTest.can_create_postal_address_and_also_look_up_geocode:131
Expecting:
"51.7525548,-1.2501191"
to match pattern:
"51.75256[\d][\d],-1.25011[\d][\d]"
PostalAddress_lookupGeocode_IntegTest$ActionImplementationIntegrationTest.will_always_lookup_as_best_as_possible:88
Expecting:
"51.7525548,-1.2501191"
to match pattern:
"51.75256[\d][\d],-1.25011[\d][\d]"
PostalAddress_update_IntegTest$ActionImplementationIntegrationTest.when_lookup_geocode_or_does_not_loookup:87
Expecting:
"51.7525548,-1.2501191"
to match pattern:
"51.75256[\d][\d],-1.25011[\d][\d]"
here's the text that has been removed
As a by-the-by, the demo app has one further "trick up its sleeve".
If you run the app you'll notice that the currently selected DemoObject
is highlighted in the left-hand table of the HomePageViewModel
.
This is accomplished by having the view model collaborate with a subscribing domain service that configures a CSS class.
We start by ensuring that the DemoObject
emits an event for its CSS class:
.DemoObject.java
@DomainObjectLayout(
...
cssClassUiEvent = DemoObject.CssClassUiEvent.class
)
public class DemoObject ... {
public static class CssClassUiEvent
extends org.apache.isis.applib.services.eventbus.CssClassUiEvent<DemoObject> {}
...
}
Next, we define the domain service to act as the subscriber.
Since it will be interact
.HomePageViewModel.java
public class HomePageViewModel ... {
@DomainService(nature = NatureOfService.DOMAIN)
public static class CssHighlighter extends AbstractSubscriber {
@EventHandler
@Subscribe
public void on(DemoObject.CssClassUiEvent ev) {
if(getContext() == null) {
return;
}
if(ev.getSource() == getContext().getSelected()) { // <1>
ev.setCssClass("selected");
}
}
private HomePageViewModel getContext() { // <2>
return (HomePageViewModel) scratchpad.get("context");
}
void setContext(final HomePageViewModel homePageViewModel) {
scratchpad.put("context", homePageViewModel);
}
@Inject
Scratchpad scratchpad; // <3>
}
}
<1> If the domain object is the currently selected then set the CSS class
<2> Provide methods to set and get the current HomePageViewModel
(acting as the context)
<3> Store the context using the Scratchpad
domain service (request-scoped so thread-safe).
The HomePageViewModel
is responsible for setting itself as the context for the domain service:
.HomePageViewModel.java
public class HomePageViewModel ... {
...
public TranslatableString title() {
cssHighlighter.setContext(this); // <1>
...
}
...
@javax.inject.Inject
CssHighlighter cssHighlighter;
}
<1> set the context on the domain service
Finally we just need some CSS, in the application.css
file:
.application.css
.selected {
font-style: italic;
font-weight: bolder;
}
from isisaddons-legacy/isis-module-security#45
bilgin:
It would be nice if users were able to create application tenancies and invite/add users though the self registration process.
Currently, the self registered users don't belong to any tenancy, and they have to be added to a tenancy after their regitration.
from isisaddons-legacy/isis-module-excel#7
oscar:
Current implementation exports and imports properties referencing other entities by writing:
As those internal ids are can be automatically generated by the datastore, the wouldn't be known when defining an initial set of entities to be imported (for example, imagine a TodoItem that references a "parent " TodoItem; all them are going to be initially imported from Excel).
The proposed solution complements current logic by trying to find the corresponding entity by means of the AutoComplete facet (if defined for the Entity). That's the more generic way on Apache Isis to search for a concrete entity using a simple String.
org.incode.module.docrendering.xdocreport.dom.impl.AbstractFieldsMetadataClassSerializer#process called recursively and can become very costly.
A work-a-round is creating DTO (for example as Innerclass) of the object(s) you are using for rendering.
from isisaddons-legacy/isis-module-sessionlogger#8
following on from earlier workaround, ticket#7
public class AbstractIsisQuartzJob implements Job {
public static enum ConcurrentInstancesPolicy {
SINGLE_INSTANCE_ONLY,
MULTIPLE_INSTANCES
}
private final AbstractIsisSessionTemplate isisRunnable;
private final ConcurrentInstancesPolicy concurrentInstancesPolicy;
private boolean executing;
public AbstractIsisQuartzJob(AbstractIsisSessionTemplate isisRunnable) {
this(isisRunnable, ConcurrentInstancesPolicy.SINGLE_INSTANCE_ONLY);
}
public AbstractIsisQuartzJob(
AbstractIsisSessionTemplate isisRunnable,
ConcurrentInstancesPolicy concurrentInstancesPolicy) {
this.isisRunnable = isisRunnable;
this.concurrentInstancesPolicy = concurrentInstancesPolicy;
}
/**
* Sets up an {@link IsisSession} then delegates to the
* {@link #doExecute(JobExecutionContext) hook}.
*/
public void execute(final JobExecutionContext context) throws JobExecutionException {
final AuthenticationSession authSession = newAuthSession(context);
try {
if(executing &&
concurrentInstancesPolicy == ConcurrentInstancesPolicy.SINGLE_INSTANCE_ONLY) {
return;
}
executing = true;
isisRunnable.execute(authSession, context);
} finally {
executing = false;
}
}
AuthenticationSession newAuthSession(JobExecutionContext context) {
String user = getKey(context, SchedulerConstants.USER_KEY);
String rolesStr = getKey(context, SchedulerConstants.ROLES_KEY);
String[] roles = Iterables.toArray(
Splitter.on(",").split(rolesStr), String.class);
return new SimpleSession(user, roles);
}
String getKey(JobExecutionContext context, String key) {
return context.getMergedJobDataMap().getString(key);
}
}
To indicate whether a communication channel is currently in use
from isisaddons-legacy/isis-module-security#29
I would like to use a shiro possibility to have multiple realms:
1.) to have in INI realm administrator uses
2.) thru this addon create additional users and authenticate them with their passwords
I've tried to adapt the AuthenticationStrategyForIsisModuleSecurityRealm, but it fails when tries to authentificate the user from addon, but failed.
Here the adapted Strategy, I've varied the subclassing of strategies, actually I would need "AtLeastOneSuccessfulStrategy" but failed
<pre>
package security;
import java.util.Collection;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.pam.AllSuccessfulStrategy;
import org.apache.shiro.realm.Realm;
/**
* Created by niv on 12.04.2016.
*/
public class AuthenticationStrategyForIsisModuleSecurityRealm2 extends AllSuccessfulStrategy {
public AuthenticationStrategyForIsisModuleSecurityRealm2() {
}
@Override
public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo auth = null;
for (Realm realm : realms) {
try {
auth = realm.getAuthenticationInfo(token);
if (auth != null)
return auth;
} catch (IncorrectCredentialsException e) {
System.out.println(e.getMessage());
// catching when single realm throws authentification exception
}
}
throw new AuthenticationException("no provided realms could't authenticate user, realm count:" + realms.size());
}
}
</pre>
Here my shiro.ini:
<pre>
_[main]
isisModuleSecurityRealm=org.isisaddons.module.security.shiro.IsisModuleSecurityRealm
authenticationStrategy=security.AuthenticationStrategyForIsisModuleSecurityRealm2
securityManager.authenticator.authenticationStrategy =$authenticationStrategy
securityManager.realms = $iniRealm,$isisModuleSecurityRealm
[users]
# user = password, role1, role2, role3, ...
sven = pass, admin_role, isis-module-security-admin
dick = pass, user_role, self-install_role
bob = pass, user_role, self-install_role
joe = pass, user_role, self-install_role
guest = guest, user_role
[roles]
user_role = *:SimpleObjects:*:*,\
*:SimpleObject:*:*
self-install_role = *:DomainAppFixtureService:*:*
admin_role = *
_
</pre>
Some place ids have a length greater than 255 characters
javax.jdo.JDOFatalUserException
Attempt to store value "......" in column "placeId" that has maximum length of 255. Please correct your data!
org.datanucleus.api.jdo.NucleusJDOHelper#getJDOExceptionForNucleusException(NucleusJDOHelper.java:616)
org.datanucleus.api.jdo.JDOPersistenceManager#jdoMakePersistent(JDOPersistenceManager.java:725)
org.datanucleus.api.jdo.JDOPersistenceManager#makePersistent(JDOPersistenceManager.java:745)
org.apache.isis.objectstore.jdo.datanucleus.persistence.commands.DataNucleusCreateObjectCommand#execute(DataNucleusCreateObjectCommand.java:54)
org.apache.isis.core.runtime.system.persistence.PersistenceSession#executeCommands(PersistenceSession.java:1253)
org.apache.isis.core.runtime.system.persistence.PersistenceSession#execute(PersistenceSession.java:1247)
select * from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME LIKE '%class%' or COLUMN_NAME like 'fully%' or COLUMN_NAME like '%fq%' or COLUMN_NAME like '%domainType%'
order by COLUMN_NAME, TABLE_NAME
which gives us:
incodeDocuments Applicability attachmentAdvisorClassName
dbo Link className
incodeDocuments Applicability domainClassName
incodeClassification Applicability domainType
isissecurity ApplicationPermission featureFqn
dbo FixedAssetRegistrationType fullyQualifiedClassName
incodeClassification Category fullyQualifiedName
incodeDocuments RenderingStrategy rendererClassName
incodeDocuments Applicability rendererModelFactoryClassName
from isisaddons-legacy/isis-module-settings#3
Probably using same mechanism as https://github.com/isisaddons/isis-module-security (jbcrypt).
The height should be used to size the canvas' wrapping div, with CSS to enable scrolling {overflow:scroll;}
For the canvas' size, it should simply be calculated from PDF page's viewport.
as per as per isisaddons-legacy/isis-wicket-pdfjs#2
from isisaddons-legacy/isis-module-command#11
Revert
isisaddons-legacy/isis-module-command#10
after Isis 1.13.1 is released with fix for ISIS-1497
from isisaddons-legacy/isis-module-security#44
This therefore means that ApplicationUser and ApplicationRole both become subclasses of ApplicationActor, with ApplicationActor ->* ApplicationRole.
There also needs to be some logic to prevent infinite loops (role A -> role B -> role C -> role A)
seems to be a classpath issue. works ok if run via IDE (org.apache.isis.WebServer) or jetty-console
this repo:
https://github.com/ppirus/quickstart/
demonstrates the issue
from isisaddons-legacy/isis-module-security#37
Kambiz wrote:
Hi,
we are trying to use the security module which would be a perfect fit
for our needs if it had a fully LDAP based implementation.
To make things even more difficult, we are building up an infrastructure
where several domains with separate databases exist.
Problem 1: the JDO annotations of the domain objects in the module
obviously don't use the DataNucleus extension to specify a different
data store than the default one.
This leads to users/roles being created in the 'default data store' of
the respective service and we are not easily able to redirect the
security related persistence towards a central 'security database'.
Problem 2: a fully LDAP based implementation is what the customer needs
If an LDAP backend is present in a company, then one would expect to
handle all of the authentication/authorisation issues on that side
without the need to have an additional database which might get out of
sync with the single source of truth which should be LDAP.
We have found out that DataNucleus even has an LDAP data store
implementation.
Would it be possible to implement a fully LDAP based backend for the
security module? We would be willing to invest some effort, if you could
guide us on how to tackle the problem.
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.