├── .git-hooks ├── post-commit ├── post-index-change ├── post-rewrite ├── pre-commit └── pre-push ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── functional-proposal.md │ ├── project.md │ └── refactoring_and_technical_evolution.md └── workflows │ ├── deploy-dev.yml │ ├── deploy.yml │ └── epics_management.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── scripts ├── on-workdir-changed.sh ├── run-linter.sh ├── run-prettier.sh ├── run-typecheck.sh └── run-yalc-publish.sh ├── src ├── frontend │ ├── .eslintrc.js │ ├── .prettierignore │ ├── LICENSE │ ├── lerna.json │ ├── nx.json │ ├── package.json │ ├── packages │ │ ├── activitypub-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── components │ │ │ │ ├── CollectionList.js │ │ │ │ ├── CommentsField │ │ │ │ │ ├── CommentsField.js │ │ │ │ │ ├── CommentsList.js │ │ │ │ │ ├── CustomMention.js │ │ │ │ │ └── PostCommentForm.js │ │ │ │ └── ReferenceCollectionField.js │ │ │ │ ├── constants.js │ │ │ │ ├── hooks │ │ │ │ ├── useAwaitActivity.ts │ │ │ │ ├── useCollection.ts │ │ │ │ ├── useInbox.ts │ │ │ │ ├── useMentions │ │ │ │ │ ├── MentionsList.js │ │ │ │ │ ├── renderMentions.js │ │ │ │ │ └── useMentions.js │ │ │ │ ├── useNodeinfo.ts │ │ │ │ ├── useOutbox.ts │ │ │ │ └── useWebfinger.js │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── utils.ts │ │ │ │ └── utils │ │ │ │ ├── index.ts │ │ │ │ ├── shaclValidation.d.ts │ │ │ │ └── shaclValidation.ts │ │ ├── auth-provider │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ ├── index.es.js.178531.2 │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── authProvider.js │ │ │ │ ├── components │ │ │ │ ├── AuthDialog.js │ │ │ │ ├── LocalLoginPage │ │ │ │ │ ├── ColorGradientProgressBar.js │ │ │ │ │ ├── LocalLoginPage.js │ │ │ │ │ ├── LoginForm.tsx │ │ │ │ │ ├── NewPasswordForm.tsx │ │ │ │ │ ├── PasswordStrengthIndicator.js │ │ │ │ │ ├── RequiredFieldIndicator.tsx │ │ │ │ │ ├── ResetPasswordForm.tsx │ │ │ │ │ ├── SignupForm.tsx │ │ │ │ │ ├── SimpleBox.js │ │ │ │ │ ├── getSearchParamsRest.js │ │ │ │ │ └── validatePasswordStrength.js │ │ │ │ ├── PermissionsButton │ │ │ │ │ ├── AddPermissionsForm.js │ │ │ │ │ ├── AgentIcon.js │ │ │ │ │ ├── AgentItem.js │ │ │ │ │ ├── EditPermissionsForm.js │ │ │ │ │ ├── PermissionsButton.js │ │ │ │ │ └── PermissionsDialog.js │ │ │ │ ├── ResourceWithPermissions.js │ │ │ │ ├── SsoLoginPage.js │ │ │ │ └── UserMenu.js │ │ │ │ ├── constants.ts │ │ │ │ ├── crud │ │ │ │ ├── create │ │ │ │ │ └── CreateWithPermissions.js │ │ │ │ ├── edit │ │ │ │ │ ├── DeleteButtonWithPermissions.js │ │ │ │ │ ├── EditActionsWithPermissions.tsx │ │ │ │ │ ├── EditButtonWithPermissions.js │ │ │ │ │ ├── EditToolbarWithPermissions.tsx │ │ │ │ │ └── EditWithPermissions.js │ │ │ │ ├── list │ │ │ │ │ ├── ListActionsWithPermissions.js │ │ │ │ │ └── ListWithPermissions.js │ │ │ │ └── show │ │ │ │ │ ├── ShowActionsWithPermissions.tsx │ │ │ │ │ └── ShowWithPermissions.js │ │ │ │ ├── hooks │ │ │ │ ├── useAgents.js │ │ │ │ ├── useCheckAuthenticated.js │ │ │ │ ├── useCheckPermissions.ts │ │ │ │ ├── usePermissionsWithRefetch.js │ │ │ │ └── useSignup.js │ │ │ │ ├── index.ts │ │ │ │ ├── messages │ │ │ │ ├── english.js │ │ │ │ └── french.js │ │ │ │ ├── passwordScorer.js │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ ├── date-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── CalendarList.js │ │ │ │ ├── DaysList.js │ │ │ │ ├── Picker.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── useFullCalendarProps.js │ │ ├── field-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── AvatarWithLabelField.js │ │ │ │ ├── MultiUrlField.js │ │ │ │ ├── QuickAppendReferenceArrayField │ │ │ │ ├── QuickAppendDialog.js │ │ │ │ ├── QuickAppendReferenceArrayField.js │ │ │ │ └── ResultsList.js │ │ │ │ ├── ReferenceArrayField.js │ │ │ │ ├── ReferenceField.js │ │ │ │ ├── SeparatedListField.js │ │ │ │ └── index.ts │ │ ├── geo-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── LocationInput.js │ │ │ │ ├── MapField │ │ │ │ ├── ChangeView.js │ │ │ │ └── MapField.js │ │ │ │ ├── MapList │ │ │ │ ├── DefaultPopupContent.js │ │ │ │ ├── MapList.js │ │ │ │ ├── MarkerClusterGroup.js │ │ │ │ ├── MobileDrawer.js │ │ │ │ └── QueryStringUpdater.js │ │ │ │ ├── extractContext.js │ │ │ │ └── index.ts │ │ ├── input-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── ImageInput.tsx │ │ │ │ ├── MultiLinesInput.js │ │ │ │ ├── MultiServerAutocompleteArrayInput.js │ │ │ │ ├── MultiServerAutocompleteInput.js │ │ │ │ ├── OptionRenderer.js │ │ │ │ ├── ReferenceArrayInput.js │ │ │ │ ├── ReferenceInput.js │ │ │ │ └── index.ts │ │ ├── interop-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── dialogs │ │ │ │ └── LexiconCreateDialog.js │ │ │ │ ├── fetch │ │ │ │ ├── fetchESCO.js │ │ │ │ └── fetchWikidata.js │ │ │ │ ├── forms │ │ │ │ ├── CreateOrImportForm.js │ │ │ │ ├── ImportForm.js │ │ │ │ └── LexiconImportForm.js │ │ │ │ ├── hooks │ │ │ │ ├── useFork.js │ │ │ │ └── useSync.js │ │ │ │ ├── index.ts │ │ │ │ └── inputs │ │ │ │ └── LexiconAutocompleteInput.js │ │ ├── list-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── ChipList.js │ │ │ │ ├── GridList.js │ │ │ │ ├── MasonryList.js │ │ │ │ ├── MultiViewsList │ │ │ │ ├── ListActionsWithViews.js │ │ │ │ ├── ListViewContext.js │ │ │ │ ├── MultiViewsList.js │ │ │ │ └── ViewsButtons.js │ │ │ │ ├── ReferenceFilter.tsx │ │ │ │ └── index.ts │ │ ├── markdown-components │ │ │ ├── README.md │ │ │ ├── dist │ │ │ │ ├── index.cjs.js │ │ │ │ ├── index.cjs.js.map │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.d.ts.map │ │ │ │ ├── index.es.js │ │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ │ ├── MarkdownField.js │ │ │ │ ├── MarkdownInput.tsx │ │ │ │ ├── index.ts │ │ │ │ └── useLoadLinks.js │ │ └── semantic-data-provider │ │ │ ├── README.md │ │ │ ├── dist │ │ │ ├── index.cjs.js │ │ │ ├── index.cjs.js.map │ │ │ ├── index.d.ts │ │ │ ├── index.d.ts.map │ │ │ ├── index.es.js │ │ │ └── index.es.js.map │ │ │ ├── package.json │ │ │ └── src │ │ │ ├── dataProvider │ │ │ ├── dataProvider.js │ │ │ ├── httpClient.js │ │ │ ├── methods │ │ │ │ ├── create.js │ │ │ │ ├── delete.ts │ │ │ │ ├── deleteMany.js │ │ │ │ ├── getDataModels.js │ │ │ │ ├── getDataServers.js │ │ │ │ ├── getList.ts │ │ │ │ ├── getMany.js │ │ │ │ ├── getManyReference.js │ │ │ │ ├── getOne.js │ │ │ │ ├── patch.ts │ │ │ │ └── update.ts │ │ │ ├── plugins │ │ │ │ ├── configureUserStorage.ts │ │ │ │ ├── fetchAppRegistration.ts │ │ │ │ ├── fetchDataRegistry.ts │ │ │ │ ├── fetchTypeIndexes.ts │ │ │ │ └── fetchVoidEndpoints.ts │ │ │ ├── types.ts │ │ │ └── utils │ │ │ │ ├── arrayOf.ts │ │ │ │ ├── buildAutoDetectBlankNodesQuery.js │ │ │ │ ├── buildBaseQuery.js │ │ │ │ ├── buildBlankNodesQuery.js │ │ │ │ ├── buildSparqlQuery.js │ │ │ │ ├── buildSparqlUriQuery.js │ │ │ │ ├── compactPredicate.ts │ │ │ │ ├── expandTypes.ts │ │ │ │ ├── fetchContainers.ts │ │ │ │ ├── fetchResource.js │ │ │ │ ├── fetchSparqlEndpoints.js │ │ │ │ ├── findContainersWithShapeTree.ts │ │ │ │ ├── findContainersWithTypes.ts │ │ │ │ ├── findContainersWithURIs.ts │ │ │ │ ├── findCreateContainerWithTypes.ts │ │ │ │ ├── getContainerFromDataRegistration.ts │ │ │ │ ├── getEmbedFrame.js │ │ │ │ ├── getOntologiesFromContext.ts │ │ │ │ ├── getPrefixFromUri.ts │ │ │ │ ├── getRdfPrefixes.js │ │ │ │ ├── getServerKeyFromType.js │ │ │ │ ├── getServerKeyFromUri.js │ │ │ │ ├── getTypesFromShapeTree.ts │ │ │ │ ├── getUploadsContainerUri.ts │ │ │ │ ├── getUriFromPrefix.ts │ │ │ │ ├── handleFiles.ts │ │ │ │ ├── normalizeConfig.ts │ │ │ │ └── parseServerKeys.ts │ │ │ ├── hooks │ │ │ ├── useCompactPredicate.ts │ │ │ ├── useContainerByUri.ts │ │ │ ├── useContainers.ts │ │ │ ├── useContainersByTypes.ts │ │ │ ├── useCreateContainerUri.ts │ │ │ ├── useDataModel.ts │ │ │ ├── useDataModels.ts │ │ │ ├── useDataProviderConfig.ts │ │ │ ├── useDataServers.ts │ │ │ ├── useGetCreateContainerUri.ts │ │ │ ├── useGetExternalLink.js │ │ │ └── useGetPrefixFromUri.ts │ │ │ ├── index.ts │ │ │ ├── notificationChannels │ │ │ └── subscribeToUpdates.ts │ │ │ └── reification │ │ │ ├── FilterHandler.js │ │ │ ├── GroupedReferenceHandler.js │ │ │ └── ReificationArrayInput.js │ ├── templates │ │ └── cra-template-dms │ │ │ ├── .eslintrc.json │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── template.json │ │ │ └── template │ │ │ ├── .env │ │ │ ├── README.md │ │ │ ├── gitignore │ │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── logo192.png │ │ │ ├── logo512.png │ │ │ └── manifest.json │ │ │ └── src │ │ │ ├── App.js │ │ │ ├── config │ │ │ ├── dataProvider.js │ │ │ ├── dataServers.js │ │ │ ├── ontologies.json │ │ │ └── resources.js │ │ │ ├── index.css │ │ │ ├── index.js │ │ │ └── resources │ │ │ └── notes.js │ ├── tsconfig.json │ └── yarn.lock ├── jena │ ├── Makefile │ ├── README.md │ ├── docker-compose.yaml │ ├── fuseki-docker │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── configuration │ │ │ ├── localData.ttl │ │ │ └── testData.ttl │ │ ├── docker-compact-entrypoint.sh │ │ ├── docker-delete-old-data-entrypoint.sh │ │ ├── docker-entrypoint.sh │ │ ├── docker-migration-entrypoint.sh │ │ ├── extra │ │ │ ├── commons-collections4-4.4.jar │ │ │ ├── jena-permissions-3.17.0.jar │ │ │ └── semapps-jena-permissions-1.0.0.jar │ │ ├── load.sh │ │ ├── migration │ │ │ ├── migrate.js │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ └── templates │ │ │ │ ├── dataset.ttl │ │ │ │ └── secure-dataset.ttl │ │ ├── shiro.ini │ │ └── tdbloader │ ├── permissions │ │ ├── .gitignore │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── org │ │ │ └── semapps │ │ │ └── jena │ │ │ └── permissions │ │ │ └── ShiroEvaluator.java │ └── tests │ │ ├── .env │ │ ├── config.js │ │ ├── package.json │ │ └── webacl │ │ ├── ACLGraph.test.js │ │ ├── ACL_test_data.ttl │ │ ├── DELETE_INSERT_with_on_Append_perm.test.js │ │ ├── anyUser_accessTo.test.js │ │ ├── blankNodes.test.js │ │ ├── groups_accessTo.test.js │ │ ├── middleware_403.test.js │ │ ├── public_accessTo.test.js │ │ ├── public_default.test.js │ │ ├── public_defaultParent.test.js │ │ ├── testData.ttl │ │ ├── user_accessTo.test.js │ │ ├── user_defaultParent.test.js │ │ └── utils.js └── middleware │ ├── .eslintrc.json │ ├── lerna.json │ ├── nx.json │ ├── package.json │ ├── packages │ ├── activitypub │ │ ├── LICENSE │ │ ├── README.md │ │ ├── constants.js │ │ ├── containers.js │ │ ├── index.js │ │ ├── mixins │ │ │ ├── activities-handler.js │ │ │ ├── await-activity.js │ │ │ ├── bot.js │ │ │ └── fake-queue.js │ │ ├── package.json │ │ ├── services │ │ │ ├── activity-mapping.js │ │ │ ├── activitypub │ │ │ │ ├── index.js │ │ │ │ └── subservices │ │ │ │ │ ├── activity-handlers │ │ │ │ │ └── setRightsHandler.js │ │ │ │ │ ├── activity.js │ │ │ │ │ ├── actor.js │ │ │ │ │ ├── api.js │ │ │ │ │ ├── collection │ │ │ │ │ ├── actions │ │ │ │ │ │ └── get.js │ │ │ │ │ └── index.js │ │ │ │ │ ├── collections-registry.js │ │ │ │ │ ├── follow.js │ │ │ │ │ ├── inbox.js │ │ │ │ │ ├── like.js │ │ │ │ │ ├── object.js │ │ │ │ │ ├── outbox.js │ │ │ │ │ ├── reply.js │ │ │ │ │ ├── share.js │ │ │ │ │ └── side-effects.js │ │ │ ├── migration.js │ │ │ └── relay.js │ │ ├── utilTypes.d.ts │ │ ├── utils.js │ │ └── utils │ │ │ └── matchActivity.js │ ├── auth │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── middlewares │ │ │ ├── localLogout.js │ │ │ ├── redirectToFront.js │ │ │ ├── saveRedirectUrl.js │ │ │ └── sendToken.js │ │ ├── mixins │ │ │ ├── auth.js │ │ │ └── auth.sso.js │ │ ├── package.json │ │ ├── services │ │ │ ├── account.js │ │ │ ├── auth.cas.js │ │ │ ├── auth.local.js │ │ │ ├── auth.oidc.js │ │ │ ├── jwt.js │ │ │ ├── mail.js │ │ │ └── migration.js │ │ └── templates │ │ │ └── reset-password │ │ │ ├── en-EN │ │ │ ├── subject.hbs │ │ │ └── text.hbs │ │ │ └── fr-FR │ │ │ ├── subject.hbs │ │ │ └── text.hbs │ ├── backup │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── indexTypes.d.ts │ │ ├── package.json │ │ └── utils │ │ │ ├── fsCopy.js │ │ │ ├── fsRemove.js │ │ │ ├── ftpCopy.js │ │ │ ├── ftpRemove.js │ │ │ └── rsyncCopy.js │ ├── core │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ ├── service.js │ │ └── serviceTypes.d.ts │ ├── crypto │ │ ├── constants.js │ │ ├── index.js │ │ ├── keys │ │ │ ├── index.js │ │ │ ├── key-container.js │ │ │ ├── keys.js │ │ │ ├── migration.js │ │ │ └── public-key-container.js │ │ ├── package.json │ │ ├── signature │ │ │ ├── http-signatures.js │ │ │ ├── index.js │ │ │ ├── keypair.js │ │ │ └── proxy.js │ │ ├── utils │ │ │ ├── noGraphCredentialContext.js │ │ │ └── utils.js │ │ └── verifiable-credentials │ │ │ ├── VcCapabilityPresentationProofPurpose.js │ │ │ ├── VcPurpose.js │ │ │ ├── challenge-service.js │ │ │ ├── data-integrity-service.js │ │ │ ├── index.js │ │ │ ├── vc-api-service.js │ │ │ ├── vc-credential-container.js │ │ │ ├── vc-holder-service.js │ │ │ ├── vc-issuer-service.js │ │ │ ├── vc-presentation-container.js │ │ │ ├── vc-service.js │ │ │ └── vc-verifier-service.js │ ├── importer │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── mixins │ │ │ ├── discourse.js │ │ │ ├── drupal.js │ │ │ ├── gogocarto.js │ │ │ ├── humhub.js │ │ │ ├── importer.js │ │ │ ├── jotform.js │ │ │ ├── mobilizon.js │ │ │ ├── prestashop.js │ │ │ ├── wordpress.js │ │ │ └── yeswiki.js │ │ ├── package.json │ │ └── utils.js │ ├── inference │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ ├── service.js │ │ └── subservices │ │ │ └── remote.js │ ├── jsonld │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ ├── service.js │ │ ├── services │ │ │ ├── api │ │ │ │ └── index.js │ │ │ ├── context │ │ │ │ ├── actions │ │ │ │ │ ├── get.js │ │ │ │ │ ├── getLocal.js │ │ │ │ │ ├── merge.js │ │ │ │ │ ├── parse.js │ │ │ │ │ └── validate.js │ │ │ │ └── index.js │ │ │ ├── document-loader │ │ │ │ └── index.js │ │ │ └── parser │ │ │ │ └── index.js │ │ └── utils │ │ │ ├── uriSchemes.js │ │ │ └── utils.js │ ├── ldp │ │ ├── LICENSE │ │ ├── README.md │ │ ├── adapter.js │ │ ├── index.js │ │ ├── mixins │ │ │ ├── controlled-container.js │ │ │ ├── dereference.js │ │ │ ├── disassembly.js │ │ │ ├── document-tagger.js │ │ │ ├── image-processor.js │ │ │ ├── mime-types.js │ │ │ ├── orphan-files-deletion.js │ │ │ ├── pseudo-id.js │ │ │ ├── single-resource-container.js │ │ │ └── special-endpoint.js │ │ ├── package.json │ │ ├── routes │ │ │ ├── getCatchAllRoute.js │ │ │ └── getPodsRoute.js │ │ ├── service.js │ │ ├── services │ │ │ ├── api │ │ │ │ ├── actions │ │ │ │ │ ├── delete.js │ │ │ │ │ ├── get.js │ │ │ │ │ ├── head.js │ │ │ │ │ ├── patch.js │ │ │ │ │ ├── post.js │ │ │ │ │ └── put.js │ │ │ │ └── index.js │ │ │ ├── cache │ │ │ │ └── index.js │ │ │ ├── container │ │ │ │ ├── actions │ │ │ │ │ ├── attach.js │ │ │ │ │ ├── clear.js │ │ │ │ │ ├── create.js │ │ │ │ │ ├── createAndAttach.js │ │ │ │ │ ├── delete.js │ │ │ │ │ ├── detach.js │ │ │ │ │ ├── exist.js │ │ │ │ │ ├── get.js │ │ │ │ │ ├── getAll.js │ │ │ │ │ ├── getPath.js │ │ │ │ │ ├── getUris.js │ │ │ │ │ ├── includes.js │ │ │ │ │ ├── isEmpty.js │ │ │ │ │ ├── patch.js │ │ │ │ │ └── post.js │ │ │ │ └── index.js │ │ │ ├── link-header │ │ │ │ ├── actions │ │ │ │ │ ├── get.js │ │ │ │ │ └── register.js │ │ │ │ └── index.js │ │ │ ├── registry │ │ │ │ ├── actions │ │ │ │ │ ├── getByType.js │ │ │ │ │ ├── getByUri.js │ │ │ │ │ ├── getUri.js │ │ │ │ │ ├── list.js │ │ │ │ │ └── register.js │ │ │ │ ├── defaultOptions.js │ │ │ │ └── index.js │ │ │ ├── remote │ │ │ │ ├── actions │ │ │ │ │ ├── delete.js │ │ │ │ │ ├── get.js │ │ │ │ │ ├── getGraph.js │ │ │ │ │ ├── getNetwork.js │ │ │ │ │ ├── getStored.js │ │ │ │ │ ├── isRemote.js │ │ │ │ │ └── store.js │ │ │ │ └── index.js │ │ │ └── resource │ │ │ │ ├── actions │ │ │ │ ├── awaitCreateComplete.js │ │ │ │ ├── create.js │ │ │ │ ├── delete.js │ │ │ │ ├── exist.js │ │ │ │ ├── generateId.js │ │ │ │ ├── get.js │ │ │ │ ├── getContainers.js │ │ │ │ ├── getTypes.js │ │ │ │ ├── patch.js │ │ │ │ ├── put.js │ │ │ │ └── upload.js │ │ │ │ ├── index.js │ │ │ │ └── methods.js │ │ ├── utilTypes.d.ts │ │ └── utils.js │ ├── middlewares │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── migration │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ ├── mime-types │ │ ├── LICENSE │ │ ├── README.md │ │ ├── constants.js │ │ ├── index.js │ │ └── package.json │ ├── nodeinfo │ │ ├── LICENSE │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ ├── notifications │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ ├── services │ │ │ ├── digest │ │ │ │ ├── service.js │ │ │ │ └── subscription.js │ │ │ ├── expo-push │ │ │ │ ├── device.js │ │ │ │ ├── notification.js │ │ │ │ └── service.js │ │ │ └── single-mail │ │ │ │ └── service.js │ │ └── templates │ │ │ └── single-mail │ │ │ ├── html.hbs │ │ │ ├── subject.hbs │ │ │ └── text.hbs │ ├── ontologies │ │ ├── LICENSE │ │ ├── README.md │ │ ├── actions │ │ │ ├── findNamespace.js │ │ │ ├── findPrefix.js │ │ │ ├── get.js │ │ │ ├── getPrefixes.js │ │ │ ├── getRdfPrefixes.js │ │ │ ├── list.js │ │ │ ├── prefixToUri.js │ │ │ └── register.js │ │ ├── index.js │ │ ├── ontologies │ │ │ ├── core │ │ │ │ ├── acl.json │ │ │ │ ├── as.json │ │ │ │ ├── cred.json │ │ │ │ ├── dc.json │ │ │ │ ├── did.json │ │ │ │ ├── foaf.json │ │ │ │ ├── index.js │ │ │ │ ├── ldp.json │ │ │ │ ├── rdf.json │ │ │ │ ├── rdfs.json │ │ │ │ ├── sec.json │ │ │ │ ├── semapps.json │ │ │ │ ├── skos.json │ │ │ │ ├── vcard.json │ │ │ │ ├── void.json │ │ │ │ └── xsd.json │ │ │ ├── custom │ │ │ │ ├── index.js │ │ │ │ ├── mp.json │ │ │ │ ├── oasis.json │ │ │ │ ├── og.json │ │ │ │ ├── pair.json │ │ │ │ ├── petr.json │ │ │ │ ├── schema.json │ │ │ │ ├── skos.json │ │ │ │ ├── syreen.json │ │ │ │ └── tutor.json │ │ │ └── solid │ │ │ │ ├── apods.json │ │ │ │ ├── index.js │ │ │ │ ├── interop.json │ │ │ │ ├── notify.json │ │ │ │ ├── oidc.json │ │ │ │ ├── pim.json │ │ │ │ └── solid.json │ │ ├── package.json │ │ ├── service.js │ │ ├── sub-services │ │ │ └── registry.js │ │ └── utils.js │ ├── solid │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ └── services │ │ │ ├── endpoint.js │ │ │ ├── notifications │ │ │ ├── channels │ │ │ │ ├── notification-channel.mixin.js │ │ │ │ ├── webhook-channel.js │ │ │ │ └── websocket-channel.js │ │ │ ├── listener.js │ │ │ └── provider.js │ │ │ ├── preferences-file.js │ │ │ ├── storage.js │ │ │ └── type-index │ │ │ ├── type-indexes.js │ │ │ └── type-registrations.js │ ├── sparql-endpoint │ │ ├── LICENSE │ │ ├── README.md │ │ ├── getRoute.js │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ ├── sync │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── middlewares │ │ │ └── objects-watcher.js │ │ ├── package.json │ │ └── services │ │ │ ├── aggregator.js │ │ │ ├── mirror.js │ │ │ └── synchronizer.js │ ├── triplestore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── actions │ │ │ ├── countTriplesOfSubject.js │ │ │ ├── deleteOrphanBlankNodes.js │ │ │ ├── dropAll.js │ │ │ ├── insert.js │ │ │ ├── query.js │ │ │ ├── tripleExist.js │ │ │ └── update.js │ │ ├── adapter.js │ │ ├── index.js │ │ ├── package.json │ │ ├── service.js │ │ ├── subservices │ │ │ └── dataset.js │ │ ├── templates │ │ │ ├── dataset.ttl │ │ │ └── secure-dataset.ttl │ │ └── utils.js │ ├── void │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ ├── webacl │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bots │ │ │ ├── authorizer.js │ │ │ └── groups-manager.js │ │ ├── index.js │ │ ├── middlewares │ │ │ ├── cacher.js │ │ │ └── webacl.js │ │ ├── package.json │ │ ├── routes │ │ │ └── getRoutes.js │ │ ├── service.js │ │ ├── services │ │ │ ├── cache │ │ │ │ └── index.js │ │ │ ├── group │ │ │ │ ├── actions │ │ │ │ │ ├── addMember.js │ │ │ │ │ ├── create.js │ │ │ │ │ ├── delete.js │ │ │ │ │ ├── exist.js │ │ │ │ │ ├── getGroups.js │ │ │ │ │ ├── getMembers.js │ │ │ │ │ ├── getUri.js │ │ │ │ │ ├── isMember.js │ │ │ │ │ └── removeMember.js │ │ │ │ └── index.js │ │ │ └── resource │ │ │ │ ├── actions │ │ │ │ ├── addRights.js │ │ │ │ ├── awaitReadRight.js │ │ │ │ ├── deleteAllRights.js │ │ │ │ ├── deleteAllUserRights.js │ │ │ │ ├── getLink.js │ │ │ │ ├── getRights.js │ │ │ │ ├── getUsersWithReadRights.js │ │ │ │ ├── hasRights.js │ │ │ │ ├── isPublic.js │ │ │ │ ├── refreshContainersRights.js │ │ │ │ ├── removeRights.js │ │ │ │ └── setRights.js │ │ │ │ └── index.js │ │ └── utils.js │ ├── webfinger │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ ├── webhooks │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ └── webid │ │ ├── LICENSE │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ └── service.js │ ├── tests │ ├── .env │ ├── .eslintrc.json │ ├── .gitignore │ ├── activitypub │ │ ├── collection-api.test.js │ │ ├── collection.test.js │ │ ├── data │ │ │ ├── actor1.json │ │ │ └── actor2.json │ │ ├── follow.test.js │ │ ├── inbox.test.js │ │ ├── initialize.js │ │ ├── jwt │ │ │ └── .gitkeep │ │ ├── like.test.js │ │ ├── message.test.js │ │ ├── object.test.js │ │ ├── outbox.test.js │ │ └── shares.test.js │ ├── arena.json │ ├── config.js │ ├── crypto │ │ ├── initialize.js │ │ ├── keys.test.js │ │ └── verifiable-credentials.test.js │ ├── docker-compose.yaml │ ├── interop │ │ ├── initialize.js │ │ ├── mirror-protected.test.js │ │ ├── mirror.test.js │ │ ├── patch-remote.test.js │ │ └── remote-inference.test.js │ ├── jest.config.js │ ├── jest.setup.js │ ├── jsonld │ │ ├── contexts │ │ │ ├── ontology1.json │ │ │ └── ontology2.json │ │ ├── initialize.js │ │ └── merge.test.js │ ├── ldp │ │ ├── api.test.js │ │ ├── av-icon.png │ │ ├── binary.test.js │ │ ├── container-path.test.js │ │ ├── container.test.js │ │ ├── headers.test.js │ │ ├── initialize.js │ │ └── resource.test.js │ ├── ontologies │ │ ├── contexts │ │ │ ├── ontology1.json │ │ │ └── ontology2.json │ │ ├── initialize.js │ │ ├── ontologies.test.js │ │ └── ontologies │ │ │ ├── ont1.json │ │ │ ├── ont2.json │ │ │ ├── ont3.json │ │ │ ├── ont4.json │ │ │ └── ont5.json │ ├── package.json │ ├── utils.js │ ├── webId │ │ └── webId.test.js │ └── webacl │ │ ├── groupCRUD.test.js │ │ ├── initialize.js │ │ ├── resourceCRUD.test.js │ │ ├── sparql-injection.test.js │ │ └── testData.ttl │ ├── tsconfig.json │ └── yarn.lock └── website ├── .gitignore ├── README.md ├── blog ├── 2019-09-25-semapps-news-1.md └── 2021-11-12-semapps-news-2.md ├── docs ├── contribute │ ├── code.md │ ├── coding-conventions.md │ ├── documentation.md │ └── style-guide.md ├── frontend │ ├── activitypub-components.md │ ├── auth-provider.md │ ├── date-components.md │ ├── field-components.md │ ├── geo-components.md │ ├── images │ │ └── multiurlfield.png │ ├── index.md │ ├── input-components.md │ ├── interop-components.md │ ├── list-components.md │ ├── markdown-components.md │ └── semantic-data-provider │ │ ├── data-model.md │ │ ├── data-servers.md │ │ ├── index.md │ │ └── plugins.md ├── guides │ ├── activitypub.md │ ├── activitypub_resources │ │ ├── loophole.png │ │ ├── mastodon-follower.png │ │ └── mastodon-note.png │ ├── dms.md │ ├── dms_resources │ │ └── homepage_dms.png │ ├── ldp-server.md │ └── ldp_resources │ │ ├── jenafuseki_localData.jpg │ │ ├── moleculer-repl.png │ │ └── query_result.png ├── middleware │ ├── activitypub │ │ ├── activities-handler.md │ │ ├── activity-mapping.md │ │ ├── index.md │ │ └── relay.md │ ├── auth.md │ ├── backup.md │ ├── core.md │ ├── crypto │ │ ├── index.md │ │ ├── keypair.md │ │ ├── keys.md │ │ ├── migration.md │ │ ├── proxy.md │ │ ├── signature.md │ │ └── verifiable-credentials.md │ ├── importer │ │ ├── discourse.md │ │ ├── drupal.md │ │ ├── gogocarto.md │ │ ├── humhub.md │ │ ├── index.md │ │ ├── jotform.md │ │ ├── mobilizon.md │ │ ├── prestashop.md │ │ ├── wordpress.md │ │ └── yeswiki.md │ ├── index.md │ ├── inference.md │ ├── jsonld │ │ ├── context.md │ │ ├── index.md │ │ └── parser.md │ ├── ldp │ │ ├── container.md │ │ ├── controlled-container.md │ │ ├── dereference.md │ │ ├── document-tagger.md │ │ ├── image-processor.md │ │ ├── index.md │ │ ├── link-header.md │ │ ├── orphan-files-deletion.md │ │ ├── registry.md │ │ ├── resource.md │ │ └── single-resource-container.md │ ├── migration.md │ ├── nodeinfo.md │ ├── notifications │ │ ├── digest.md │ │ ├── index.md │ │ └── single-mail.md │ ├── ontologies.md │ ├── solid │ │ ├── index.md │ │ ├── notifications-listener.md │ │ ├── notifications-provider.md │ │ ├── pod.md │ │ ├── type-indexes.md │ │ └── type-registrations.md │ ├── sparql-endpoint.md │ ├── sync │ │ ├── aggregator.md │ │ ├── index.md │ │ ├── mirror.md │ │ ├── objects-watcher.md │ │ └── synchronizer.md │ ├── triplestore │ │ ├── dataset.md │ │ └── index.md │ ├── void.md │ ├── webacl │ │ ├── authorizer.md │ │ ├── group.md │ │ ├── groups-manager.md │ │ ├── index.md │ │ └── resource.md │ ├── webfinger.md │ ├── webhooks.md │ └── webid.md ├── others │ ├── PropertiesContainer.md │ ├── auth.txt │ └── reifiedRelation.md └── triplestore │ ├── compacting-datasets.md │ ├── index.md │ ├── migrating-datasets.md │ ├── moving-datasets.md │ └── webacl-implementation.md ├── docusaurus.config.js ├── i18n └── fr │ ├── code.json │ ├── docusaurus-plugin-content-blog │ ├── 2019-09-25-semapps-news-1.md │ └── 2021-11-12-semapps-news-2.md │ ├── docusaurus-plugin-content-docs │ ├── current.json │ └── current │ │ └── contribute │ │ └── documentation.md │ └── docusaurus-theme-classic │ ├── footer.json │ └── navbar.json ├── package.json ├── sidebars.js ├── src ├── css │ └── custom.css └── pages │ ├── base.module.scss │ ├── index.js │ ├── index │ ├── CubesIcon.js │ ├── Product.js │ ├── Tool.js │ ├── Website.js │ └── index.module.scss │ ├── team.js │ └── team │ ├── Member.js │ ├── Subtitle.js │ └── team.module.scss ├── static └── img │ ├── 100-lieux-cover.png │ ├── Thomas-Francart.jpg │ ├── activity-pods.png │ ├── activitypub-bridge.png │ ├── activitypub-icon.svg │ ├── archipelago.png │ ├── aurba-cover.png │ ├── av-baniere.png │ ├── av-icon.png │ ├── bastien-siguier.jfif │ ├── bienvenue-chez-moi.png │ ├── blank-profile-picture.png │ ├── cdlt-cover.png │ ├── cdlt.jpg │ ├── collectif-emploi.png │ ├── dreamstime_s_23213432.jpg │ ├── favicon.ico │ ├── guillaume-rouyer.jpg │ ├── logo-4ch-fb.png │ ├── logo-ademe.png │ ├── logo-ademe.svg │ ├── logo-afaup.png │ ├── logo-afaup.webp │ ├── logo-aurba.jpg │ ├── logo-aurba.png │ ├── logo-av.jpg │ ├── logo-cdlt.png │ ├── logo-classe-dehors.png │ ├── logo-colibris.svg │ ├── logo-dfc.png │ ├── logo-energie-partagee.png │ ├── logo-flodio.png │ ├── logo-lacoop.png │ ├── logo-petr.png │ ├── logo-petr.webp │ ├── logo-utt.png │ ├── logo.png │ ├── logo.svg │ ├── logo_dark.png │ ├── maxime_lecoq.jpeg │ ├── minicourses.png │ ├── niko.png │ ├── organigraph.png │ ├── pierre-bouvier-muller.png │ ├── ra-icon.svg │ ├── react-icon.svg │ ├── simon-louvet.jpg │ ├── solid-icon.svg │ ├── srosset.jpg │ ├── sw-icon.svg │ ├── toolbox.jpg │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ ├── undraw_docusaurus_tree.svg │ ├── vincent-farcy.png │ └── yannick-duthe.png └── yarn.lock /.git-hooks/post-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git update-index -g 3 | -------------------------------------------------------------------------------- /.git-hooks/post-index-change: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Catch cases where the work dir changed after a git command. 4 | # In that cases, run ./scripts/on-workdir-changed.sh 5 | 6 | 7 | function in_rebase { 8 | git_dir=$(git rev-parse --git-dir) 9 | # Check if git_dir/rebase-merge or /rebase_apply exist. 10 | # Then return the result 11 | return $([ -d "$git_dir/rebase-merge" ] || [ -d "$git_dir/rebase-apply" ]) 12 | } 13 | 14 | ROOT_DIR=$(git rev-parse --show-toplevel) 15 | cd "$ROOT_DIR" 16 | 17 | # If in rebase, this hook is called multiple times. 18 | # Skip here and wait for post-rewrite to have been called. 19 | if in_rebase; then 20 | exit 0 21 | fi 22 | 23 | 24 | # Get first argument. If it is 1, this indicates, working dir files have changed. 25 | if [ "$1" = 1 ] ; then 26 | ./scripts/on-workdir-changed.sh 27 | fi 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /.git-hooks/post-rewrite: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Catch cases where the work dir changed after a git rebase. 4 | # In that cases, run ./scripts/on-workdir-changed.sh 5 | 6 | 7 | # If coming from a rewrite-rebase ($1 == rebase), run on-workdir-changed. 8 | if [ "$1" = "rebase" ] ; then 9 | # cd to root directory 10 | ROOT_DIR=$(git rev-parse --show-toplevel) 11 | cd "$ROOT_DIR" 12 | 13 | ./scripts/on-workdir-changed.sh 14 | fi 15 | -------------------------------------------------------------------------------- /.git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script runs the linter and prettier for staged files 4 | # in the middleware and frontend packages. 5 | 6 | 7 | # Skip, if flag is set. 8 | if [ "$SKIP_PRECOMMIT_CHECKS" = true ] || [ "$SKIP_PRECOMMIT_CHECKS" = 1 ] ; then 9 | echo "=== Skipping pre-commit prettier run ===" 10 | exit 0 11 | fi 12 | 13 | # cd to root directory. 14 | ROOT_DIR=$(git rev-parse --show-toplevel) 15 | cd "$ROOT_DIR" 16 | 17 | 18 | # Select staged files. 19 | FILES="$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g' | xargs -r realpath | sed 's/.*/"&"/')" 20 | [ -z "$FILES" ] && echo "=== Nothing to do ===" && exit 0 21 | 22 | ## Run scripts 23 | 24 | ./scripts/run-linter.sh $FILES 25 | if [ $? != 0 ]; then 26 | exit $? 27 | fi 28 | 29 | ./scripts/run-prettier.sh $FILES 30 | if [ $? != 0 ]; then 31 | exit $? 32 | fi 33 | 34 | 35 | # Add back the modified/prettified files to staging 36 | echo "$FILES" | xargs -r git add 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /.git-hooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Skip pre-push checks if SKIP_PREPUSH_CHECKS is set. 4 | if [ "$SKIP_PREPUSH_CHECKS" = true ] || [ "$SKIP_PREPUSH_CHECKS" = 1 ] ; then 5 | echo "=== Skipping pre-push checks ===" 6 | exit 0 7 | fi 8 | 9 | cd "$ROOT_DIR" 10 | 11 | ./scripts/run-typecheck.sh 12 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: semapps 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Faites remontez un disfonctionnement dans le code actuel 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Décrivez le bug** 11 | Une description claire et concise du bug. 12 | 13 | **Etapes pour reproduire** 14 | 1. Aller sur '...' 15 | 2. Cliquer sur '....' 16 | 3. Voir l'erreur 17 | 18 | **Comportement attendu** 19 | Une description claire et concise de ce que à vous vous seriez attendu. 20 | 21 | **Captures d'écran** 22 | Si ça peut être utile, ajoutez ici des captures d'écrans pour expliquer le problème. 23 | 24 | **Système** 25 | Si c'est bug côté frontend, indiquez votre navigateur et sa version. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/functional-proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature suggestion 3 | about: Suggest an improvement or a new feature 4 | title: ‘’ 5 | labels: ‘’ 6 | assigned: ‘’ 7 | 8 | --- 9 | 10 | **Problem 11 | Is your proposal linked to a problem? Describe it here. 12 | 13 | **Proposal** 14 | A clear and concise description of what you are proposing. 15 | 16 | **Alternatives** 17 | A description of alternatives you have thought of. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/project.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Project 3 | about: Projects group several issues and focus on a significant development task. 4 | title: '' 5 | labels: project 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description** 11 | 12 | **Prerequisites before estimation** 13 | - [ ] Title of linked issue # 14 | 15 | **Linked Issues** 16 | - [ ] Title of linked issue # 17 | 18 | **Estimated work time in hours** 19 | - @srosset81: 20 | - @simonLouvet: 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/refactoring_and_technical_evolution.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Refactoring and technical evolution 3 | about: Suggest improvements to existing code (refactoring, restructuring, change of component responsibility, etc.) 4 | title: ‘’ 5 | labels: ‘’ 6 | assignees: ‘’ 7 | 8 | --- 9 | 10 | **Issue** 11 | Describe what is wrong with the current code. 12 | 13 | **Components affected** 14 | List the components affected (Moleculer services, NPM packages, etc.). 15 | 16 | **Proposal** 17 | Describe the proposed technical change and why it would improve the project. 18 | -------------------------------------------------------------------------------- /.github/workflows/deploy-dev.yml: -------------------------------------------------------------------------------- 1 | name: Deploy dev.semapps.org 2 | 3 | on: 4 | push: 5 | branches: ['next'] 6 | paths: ['website/**'] 7 | # Allows you to run this workflow manually from the Actions tab on GitHub. 8 | workflow_dispatch: 9 | 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: build and start docker container 15 | uses: appleboy/ssh-action@v1.0.3 16 | with: 17 | host: semapps.org 18 | username: ${{ secrets.USERNAME }} 19 | key: ${{ secrets.PRIVATE_KEY }} 20 | port: 22 21 | script: | 22 | cd deployment_semapps_av 23 | docker system prune 24 | docker compose build semapps-website-dev 25 | docker compose up -d semapps-website-dev 26 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy semapps.org 2 | 3 | on: 4 | push: 5 | branches: ['master'] 6 | paths: ['website/**'] 7 | # Allows you to run this workflow manually from the Actions tab on GitHub. 8 | workflow_dispatch: 9 | 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: build and start docker container 15 | uses: appleboy/ssh-action@v1.0.3 16 | with: 17 | host: semapps.org 18 | username: ${{ secrets.USERNAME }} 19 | key: ${{ secrets.PRIVATE_KEY }} 20 | port: 22 21 | script: | 22 | cd deployment_semapps_av 23 | docker system prune 24 | docker compose build semapps-website 25 | docker compose up -d semapps-website 26 | -------------------------------------------------------------------------------- /.github/workflows/epics_management.yml: -------------------------------------------------------------------------------- 1 | name: Epics management 2 | 3 | on: 4 | issues: 5 | types: [opened, created, closed, reopened, deleted] 6 | 7 | jobs: 8 | epics: 9 | runs-on: ubuntu-latest 10 | name: Update epic issues 11 | steps: 12 | - name: Run epics action 13 | uses: cloudaper/epics-action@v1 14 | with: 15 | github-token: ${{secrets.GITHUB_TOKEN}} 16 | epic-label-name: chantier 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /deploy/certbot/ 2 | /data 3 | node_modules 4 | yarn-error.log 5 | lerna-debug.log 6 | .DS_Store 7 | /.idea 8 | /data 9 | *.swp 10 | .parcel-cache 11 | .classpath 12 | .project 13 | .settings 14 | # conflict 15 | *.orig 16 | .nx 17 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.cjs.js 2 | *.es.js 3 | **/dist/** 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 120, 4 | "trailingComma": "none", 5 | "arrowParens": "avoid" 6 | } 7 | -------------------------------------------------------------------------------- /scripts/on-workdir-changed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is called when a git command possibly modified files in the working dir. 4 | 5 | 6 | ROOT_DIR=$(git rev-parse --show-toplevel) 7 | cd "$ROOT_DIR" 8 | 9 | ./scripts/run-yalc-publish.sh -------------------------------------------------------------------------------- /scripts/run-prettier.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to run prettier on staged files before commit. 4 | # This is called by `.git-hooks/pre-commit` 5 | 6 | 7 | echo "=== Running prettier ===" 8 | 9 | FILES="$@" 10 | 11 | ROOT_DIR=$(git rev-parse --show-toplevel) 12 | 13 | MIDDLEWARE_FILES="$(echo "$FILES" | grep -E "src/middleware" | xargs -r realpath | sed 's/.*/"&"/')" 14 | FRONTEND_FILES="$(echo "$FILES" | grep -E "src/frontend" | xargs -r realpath | sed 's/.*/"&"/')" 15 | 16 | 17 | # Run prettier on all given files. 18 | cd "$ROOT_DIR"/src/middleware 19 | echo "$MIDDLEWARE_FILES" | xargs npx prettier --write --ignore-unknown 20 | cd "$ROOT_DIR"/src/frontend 21 | echo "$FRONTEND_FILES" | xargs npx prettier --write --ignore-unknown 22 | cd "$ROOT_DIR" 23 | 24 | if [ $? != 0 ]; then 25 | echo "⛔ Something went wrong running prettier. Have you run \`npm install\` yet?" 26 | echo " You can skip pre-commit checks by setting \$SKIP_PRECOMMIT_CHECKS" 27 | exit 1 28 | fi 29 | 30 | echo "✅ Prettier done!" 31 | 32 | exit 0 -------------------------------------------------------------------------------- /scripts/run-typecheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to typecheck frontend code. 4 | # Called by pre-push hook. 5 | 6 | ROOT_DIR=$(git rev-parse --show-toplevel) 7 | cd "$ROOT_DIR"/src/frontend 8 | 9 | echo "=== Running typecheck for frontend ===" 10 | 11 | yarn typecheck > /dev/null 12 | if [ $? -ne 0 ]; then 13 | echo "⛔ Typecheck failed! To see the errors, run \`yarn typecheck\` in the frontend directory." 14 | echo " You can skip pre-push checks by setting \$SKIP_PREPUSH_CHECKS=true" 15 | exit 1 16 | fi 17 | echo "✅ Typecheck successful!" -------------------------------------------------------------------------------- /scripts/run-yalc-publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to run yalc:publish. 4 | # Called by on-workdir-changed.sh 5 | 6 | 7 | if [ "$SKIP_YALC_PUBLISH" = true ] || [ "$SKIP_YALC_PUBLISH" = 1 ] ; then 8 | echo "=== Skipping yalc:publish ===" 9 | exit 0 10 | fi 11 | 12 | 13 | echo === Running yalc:publish === 14 | 15 | ROOT_DIR=$(git rev-parse --show-toplevel) 16 | cd "$ROOT_DIR"/src/frontend 17 | 18 | # Run yalc:publish. If not available, just print an info message. 19 | yarn yalc:publish &> /dev/null || \ 20 | echo "⚠️ yarn or yalc is not installed. Skipping yalc:publish" 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /src/frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | *.cjs.js 2 | *.es.js 3 | -------------------------------------------------------------------------------- /src/frontend/lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.1.3", 3 | "npmClient": "yarn", 4 | "useNx": true, 5 | "packages": ["packages/*", "templates/**"], 6 | "command": { 7 | "version": { 8 | "allowBranch": ["master", "next"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/frontend/nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasksRunnerOptions": { 3 | "default": { 4 | "runner": "nx/tasks-runners/default", 5 | "options": { 6 | "useDaemonProcess": false, 7 | "cacheableOperations": ["build", "yalc:publish"] 8 | } 9 | } 10 | }, 11 | "affected": { 12 | "defaultBase": "master" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin components for ActivityPub display 2 | 3 | ## Development 4 | 5 | ### `yarn run build` 6 | 7 | Build the library in CommonJS and ES mode. 8 | This command should always be run before publishing. 9 | 10 | ### `yarn run watch` 11 | 12 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 13 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/src/components/CollectionList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useList, ListContextProvider, useGetMany } from 'react-admin'; 3 | import useCollection from '../hooks/useCollection'; 4 | 5 | const CollectionList = ({ collectionUrl, resource, children }) => { 6 | if (React.Children.count(children) !== 1) { 7 | throw new Error(' only accepts a single child'); 8 | } 9 | 10 | const { items: actorsUris } = useCollection(collectionUrl); 11 | 12 | const { data, isLoading, isFetching } = useGetMany( 13 | resource, 14 | { ids: Array.isArray(actorsUris) ? actorsUris : [actorsUris] }, 15 | { enabled: !!actorsUris } 16 | ); 17 | 18 | const listContext = useList({ data, isLoading, isFetching }); 19 | 20 | return {children}; 21 | }; 22 | 23 | export default CollectionList; 24 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/src/components/ReferenceCollectionField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useRecordContext } from 'react-admin'; 3 | import CollectionList from './CollectionList'; 4 | 5 | const ReferenceCollectionField = ({ source, reference, children, ...rest }) => { 6 | const record = useRecordContext(); 7 | 8 | if (React.Children.count(children) !== 1) { 9 | throw new Error(' only accepts a single child'); 10 | } 11 | 12 | if (!record || !record[source]) return null; 13 | 14 | return ( 15 | 16 | {children} 17 | 18 | ); 19 | }; 20 | 21 | export default ReferenceCollectionField; 22 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/src/index.ts: -------------------------------------------------------------------------------- 1 | // Components 2 | export { default as CommentsField } from './components/CommentsField/CommentsField'; 3 | export { default as CollectionList } from './components/CollectionList'; 4 | export { default as ReferenceCollectionField } from './components/ReferenceCollectionField'; 5 | 6 | // Hooks 7 | export { default as useCollection } from './hooks/useCollection'; 8 | export { default as useInbox } from './hooks/useInbox'; 9 | export { default as useNodeinfo } from './hooks/useNodeinfo'; 10 | export { default as useOutbox } from './hooks/useOutbox'; 11 | export { default as useWebfinger } from './hooks/useWebfinger'; 12 | export { default as useMentions } from './hooks/useMentions/useMentions'; 13 | 14 | // Constants 15 | export { ACTIVITY_TYPES, ACTOR_TYPES, OBJECT_TYPES, PUBLIC_URI } from './constants'; 16 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/src/utils.ts: -------------------------------------------------------------------------------- 1 | export const arrayOf = (value: T | T[]) => { 2 | // If the field is null-ish, we suppose there are no values. 3 | if (value === null || value === undefined) { 4 | return []; 5 | } 6 | // Return as is. 7 | if (Array.isArray(value)) { 8 | return value; 9 | } 10 | // Single value is made an array. 11 | return [value]; 12 | }; 13 | 14 | export default { 15 | arrayOf 16 | }; 17 | 18 | export const filterDuplicates = (iterable: T[], predicate: (item: T) => string) => { 19 | const seen = new Set(); 20 | return iterable.filter(item => { 21 | const key = predicate(item); 22 | if (seen.has(key)) { 23 | return false; 24 | } 25 | seen.add(key); 26 | return true; 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shaclValidation'; 2 | -------------------------------------------------------------------------------- /src/frontend/packages/activitypub-components/src/utils/shaclValidation.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@semapps/activitypub-components' { 2 | export function parseJsonLd(jsonLdObj: object): Promise; 3 | export function getShaclValidator(shapeUri: string): Promise<{ success: boolean; validator?: any; error?: Error }>; 4 | } 5 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin auth provider for SemApps 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/auth-provider). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/components/LocalLoginPage/PasswordStrengthIndicator.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ColorGradientProgressBar from './ColorGradientProgressBar'; 3 | import { defaultScorer } from '../../passwordScorer'; 4 | 5 | export default function PasswordStrengthIndicator({ scorer = defaultScorer, password, ...restProps }) { 6 | const strength = scorer.scoreFn(password); 7 | return ; 8 | } 9 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/components/LocalLoginPage/getSearchParamsRest.js: -------------------------------------------------------------------------------- 1 | const USED_SEARCH_PARAMS = ['signup', 'reset_password', 'new_password', 'email', 'force-email']; 2 | 3 | const getSearchParamsRest = searchParams => { 4 | const rest = []; 5 | for (const [key, value] of searchParams.entries()) { 6 | if (!USED_SEARCH_PARAMS.includes(key)) { 7 | rest.push(`${key}=${encodeURIComponent(value)}`); 8 | } 9 | } 10 | return rest.length > 0 ? rest.join('&') : ''; 11 | }; 12 | 13 | export default getSearchParamsRest; 14 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/components/LocalLoginPage/validatePasswordStrength.js: -------------------------------------------------------------------------------- 1 | import { defaultScorer } from '../../passwordScorer'; 2 | 3 | const validatePasswordStrength = (scorer = defaultScorer) => value => { 4 | if (!scorer) return undefined; 5 | const strength = scorer.scoreFn(value); 6 | if (strength < scorer.minRequiredScore) { 7 | return 'auth.input.password_too_weak'; 8 | } 9 | return undefined; 10 | }; 11 | 12 | export default validatePasswordStrength; 13 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/components/PermissionsButton/AgentIcon.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PublicIcon from '@mui/icons-material/Public'; 3 | import VpnLockIcon from '@mui/icons-material/VpnLock'; 4 | import PersonIcon from '@mui/icons-material/Person'; 5 | import GroupIcon from '@mui/icons-material/Group'; 6 | import { CLASS_AGENT, GROUP_AGENT, USER_AGENT, ANONYMOUS_AGENT } from '../../constants'; 7 | 8 | const AgentIcon = ({ agent }) => { 9 | switch (agent.predicate) { 10 | case CLASS_AGENT: 11 | return agent.id === ANONYMOUS_AGENT ? : ; 12 | case USER_AGENT: 13 | return ; 14 | case GROUP_AGENT: 15 | return ; 16 | default: 17 | throw new Error(`Unknown agent predicate: ${agent.predicate}`); 18 | } 19 | }; 20 | 21 | export default AgentIcon; 22 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/components/PermissionsButton/EditPermissionsForm.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { List } from '@mui/material'; 3 | import { styled } from '@mui/system'; 4 | import AgentItem from './AgentItem'; 5 | 6 | const StyledList = styled(List)(({ theme }) => ({ 7 | width: '100%', 8 | maxWidth: '100%', 9 | backgroundColor: theme.palette.background.paper 10 | })); 11 | 12 | const EditPermissionsForm = ({ isContainer, agents, addPermission, removePermission }) => { 13 | return ( 14 | 15 | {Object.entries(agents).map(([agentId, agent]) => ( 16 | 23 | ))} 24 | 25 | ); 26 | }; 27 | 28 | export default EditPermissionsForm; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/components/ResourceWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Resource, usePermissions } from 'react-admin'; 3 | import { useCreateContainerUri } from '@semapps/semantic-data-provider'; 4 | import { rightsToCreate } from '../constants'; 5 | 6 | // Not used for now. The ListWithPermissions component will handle the conditional display of the Create button. 7 | const ResourceWithPermission = ({ name, create, ...rest }) => { 8 | const createContainer = useCreateContainerUri(name); 9 | const { permissions } = usePermissions(createContainer); 10 | return ( 11 | rightsToCreate.includes(p['acl:mode'])) ? create : undefined} 15 | // Requesting permissions to list container is too long, we will avoid that for now 16 | // list={permissions && permissions.some(p => rightsToList.includes(p['acl:mode'])) ? list : undefined} 17 | /> 18 | ); 19 | }; 20 | 21 | export default ResourceWithPermission; 22 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/create/CreateWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Create, CreateActions, useResourceContext } from 'react-admin'; 3 | import { useCreateContainerUri } from '@semapps/semantic-data-provider'; 4 | import useCheckPermissions from '../../hooks/useCheckPermissions'; 5 | 6 | const CreateWithPermissions = props => { 7 | const resource = useResourceContext(); 8 | const createContainerUri = useCreateContainerUri(resource); 9 | useCheckPermissions(createContainerUri, 'create'); 10 | return ; 11 | }; 12 | 13 | CreateWithPermissions.defaultProps = { 14 | actions: 15 | }; 16 | 17 | export default CreateWithPermissions; 18 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/edit/DeleteButtonWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DeleteButton, useGetRecordId, usePermissions } from 'react-admin'; 3 | import { rightsToDelete } from '../../constants'; 4 | 5 | const DeleteButtonWithPermissions = props => { 6 | const recordId = useGetRecordId(); 7 | const { permissions, isLoading } = usePermissions(recordId); 8 | if (!isLoading && permissions?.some(p => rightsToDelete.includes(p['acl:mode']))) { 9 | return ; 10 | } 11 | return null; 12 | }; 13 | 14 | export default DeleteButtonWithPermissions; 15 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/edit/EditButtonWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { EditButton, useGetRecordId, usePermissions } from 'react-admin'; 3 | import { rightsToEdit } from '../../constants'; 4 | 5 | const EditButtonWithPermissions = props => { 6 | const recordId = useGetRecordId(); 7 | const { permissions, isLoading } = usePermissions(recordId); 8 | if (!isLoading && permissions?.some(p => rightsToEdit.includes(p['acl:mode']))) { 9 | return ; 10 | } 11 | return null; 12 | }; 13 | 14 | export default EditButtonWithPermissions; 15 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/edit/EditToolbarWithPermissions.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SaveButton, Toolbar, ToolbarProps } from 'react-admin'; 3 | import { styled } from '@mui/material/styles'; 4 | import DeleteButtonWithPermissions from './DeleteButtonWithPermissions'; 5 | 6 | const StyledToolbar = styled(Toolbar)(() => ({ 7 | flex: 1, 8 | display: 'flex', 9 | justifyContent: 'space-between' 10 | })); 11 | 12 | const EditToolbarWithPermissions: React.FunctionComponent = props => ( 13 | 14 | 15 | 16 | 17 | ); 18 | 19 | export default EditToolbarWithPermissions; 20 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/edit/EditWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Edit, useGetRecordId } from 'react-admin'; 3 | import EditActionsWithPermissions from './EditActionsWithPermissions'; 4 | import EditToolbarWithPermissions from './EditToolbarWithPermissions'; 5 | import useCheckPermissions from '../../hooks/useCheckPermissions'; 6 | 7 | const EditWithPermissions = props => { 8 | const recordId = useGetRecordId(); 9 | useCheckPermissions(recordId, 'edit'); 10 | return ( 11 | 12 | {React.cloneElement(props.children, { 13 | toolbar: , 14 | // Allow to override toolbar 15 | ...props.children.props 16 | })} 17 | 18 | ); 19 | }; 20 | 21 | EditWithPermissions.defaultProps = { 22 | actions: 23 | }; 24 | 25 | export default EditWithPermissions; 26 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/list/ListWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { List } from 'react-admin'; 3 | import ListActionsWithPermissions from './ListActionsWithPermissions'; 4 | 5 | const ListWithPermissions = props => ; 6 | 7 | ListWithPermissions.defaultProps = { 8 | actions: 9 | }; 10 | 11 | export default ListWithPermissions; 12 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/crud/show/ShowWithPermissions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Show, useGetRecordId } from 'react-admin'; 3 | import ShowActionsWithPermissions from './ShowActionsWithPermissions'; 4 | import useCheckPermissions from '../../hooks/useCheckPermissions'; 5 | 6 | const ShowWithPermissions = props => { 7 | const recordId = useGetRecordId(); 8 | useCheckPermissions(recordId, 'show'); 9 | return ; 10 | }; 11 | 12 | ShowWithPermissions.defaultProps = { 13 | actions: 14 | }; 15 | 16 | export default ShowWithPermissions; 17 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/hooks/useCheckAuthenticated.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useGetIdentity, useNotify, useRedirect } from 'react-admin'; 3 | import { useLocation } from 'react-router-dom'; 4 | 5 | const useCheckAuthenticated = message => { 6 | const { data: identity, isLoading } = useGetIdentity(); 7 | const notify = useNotify(); 8 | const redirect = useRedirect(); 9 | const location = useLocation(); 10 | 11 | useEffect(() => { 12 | if (!isLoading && !identity?.id) { 13 | notify(message || 'ra.auth.auth_check_error', { type: 'error' }); 14 | redirect(`/login?redirect=${encodeURIComponent(location.pathname + location.search)}`); 15 | } 16 | }, [isLoading, identity, redirect, notify, location]); 17 | 18 | return { identity, isLoading }; 19 | }; 20 | 21 | export default useCheckAuthenticated; 22 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/hooks/useCheckPermissions.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { usePermissions, useRedirect, useNotify } from 'react-admin'; 3 | import { rights, forbiddenErrors } from '../constants'; 4 | import { Permissions } from '../types'; 5 | 6 | const useCheckPermissions = (uri: string, mode: keyof typeof rights, redirectUrl: string = '/') => { 7 | const { permissions } = usePermissions(uri); 8 | const notify = useNotify(); 9 | const redirect = useRedirect(); 10 | 11 | useEffect(() => { 12 | if (permissions && !permissions.some(p => rights[mode].includes(p['acl:mode']))) { 13 | notify(forbiddenErrors[mode], { type: 'error' }); 14 | redirect(redirectUrl); 15 | } 16 | }, [permissions, redirect, notify]); 17 | 18 | return permissions; 19 | }; 20 | 21 | export default useCheckPermissions; 22 | -------------------------------------------------------------------------------- /src/frontend/packages/auth-provider/src/hooks/useSignup.js: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { useAuthProvider } from 'react-admin'; 3 | 4 | const useSignup = () => { 5 | const authProvider = useAuthProvider(); 6 | 7 | return useCallback((params = {}) => authProvider.signup(params), [authProvider]); 8 | }; 9 | 10 | export default useSignup; 11 | -------------------------------------------------------------------------------- /src/frontend/packages/date-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin components for date display and input 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/date-components). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/date-components/src/DaysList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import FullCalendar from '@fullcalendar/react'; 3 | import listPlugin from '@fullcalendar/list'; 4 | import makeStyles from '@mui/styles/makeStyles'; 5 | import useFullCalendarProps from './useFullCalendarProps'; 6 | 7 | const useGlobalStyles = makeStyles(theme => ({ 8 | '@global': { 9 | '.fc-button': { 10 | backgroundColor: `${theme.palette.primary.main} !important`, 11 | border: 'none !important', 12 | opacity: '1 !important' 13 | } 14 | } 15 | })); 16 | 17 | const DaysList = props => { 18 | const fullCalendarProps = useFullCalendarProps(props); 19 | useGlobalStyles(); 20 | 21 | return ; 22 | }; 23 | 24 | DaysList.defaultProps = { 25 | linkType: 'edit' 26 | }; 27 | 28 | export default DaysList; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/field-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin field components for SemApps 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/field-components). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/field-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/field-components", 3 | "version": "1.1.3", 4 | "description": "React-Admin field components for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "source": "src/index.ts", 8 | "main": "dist/index.cjs.js", 9 | "module": "dist/index.es.js", 10 | "files": [ 11 | "dist" 12 | ], 13 | "scripts": { 14 | "build": "parcel build && yalc publish --push --changed", 15 | "watch": "nodemon --ext ts,tsx,js --watch src --exec 'yarn build'" 16 | }, 17 | "dependencies": { 18 | "@semapps/semantic-data-provider": "1.1.3", 19 | "lodash.debounce": "^4.0.8", 20 | "react-icons": "^4.4.0" 21 | }, 22 | "peerDependencies": { 23 | "@mui/icons-material": "^5.13.1", 24 | "@mui/material": "^5.13.1", 25 | "@mui/styles": "^5.13.1", 26 | "react": "^18.2.0", 27 | "react-admin": "^4.11.0", 28 | "react-hook-form": "^7.43.9" 29 | }, 30 | "publishConfig": { 31 | "access": "public" 32 | }, 33 | "types": "dist/index.d.ts" 34 | } 35 | -------------------------------------------------------------------------------- /src/frontend/packages/field-components/src/ReferenceArrayField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ReferenceArrayField as RaReferenceArrayField, useRecordContext, RecordContextProvider } from 'react-admin'; 3 | 4 | const ReferenceArrayField = ({ source, ...otherProps }) => { 5 | const record = useRecordContext(); 6 | if (record?.[source]) { 7 | if (!Array.isArray(record[source])) { 8 | record[source] = [record[source]]; 9 | } 10 | record[source] = record[source].map(i => i['@id'] || i.id || i); 11 | } 12 | return ( 13 | 14 | 15 | 16 | ); 17 | }; 18 | 19 | export default ReferenceArrayField; 20 | -------------------------------------------------------------------------------- /src/frontend/packages/field-components/src/ReferenceField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ReferenceField as RaReferenceField, useRecordContext, RecordContextProvider } from 'react-admin'; 3 | 4 | const ReferenceField = ({ source, ...otherProps }) => { 5 | const record = useRecordContext(); 6 | if (record[source]) { 7 | if (typeof record[source] === 'object') { 8 | record[source] = record[source]['@id'] || record[source].id; 9 | } 10 | } 11 | return ( 12 | 13 | 14 | 15 | ); 16 | }; 17 | 18 | export default ReferenceField; 19 | -------------------------------------------------------------------------------- /src/frontend/packages/field-components/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AvatarWithLabelField } from './AvatarWithLabelField'; 2 | export { default as ReferenceArrayField } from './ReferenceArrayField'; 3 | export { default as ReferenceField } from './ReferenceField'; 4 | export { default as QuickAppendReferenceArrayField } from './QuickAppendReferenceArrayField/QuickAppendReferenceArrayField'; 5 | export { default as MultiUrlField } from './MultiUrlField'; 6 | export { default as SeparatedListField } from './SeparatedListField'; 7 | -------------------------------------------------------------------------------- /src/frontend/packages/geo-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin components for geographic data display and input 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/geo-components). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/geo-components/src/MapField/ChangeView.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useMap } from 'react-leaflet'; 3 | 4 | const ChangeView = ({ center, zoom }) => { 5 | const map = useMap(); 6 | map.setView(center, zoom); 7 | return null; 8 | }; 9 | 10 | export default ChangeView; 11 | -------------------------------------------------------------------------------- /src/frontend/packages/geo-components/src/MapList/DefaultPopupContent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ShowButton, EditButton, useResourceDefinition, useRecordContext } from 'react-admin'; 3 | import { Typography } from '@mui/material'; 4 | 5 | const DefaultPopupContent = () => { 6 | const record = useRecordContext(); 7 | const resourceDefinition = useResourceDefinition({}); 8 | if (!record) return null; 9 | return ( 10 | <> 11 | {record.label && {record.label}} 12 | {record.description && ( 13 | 14 | {record.description.length > 150 ? `${record.description.substring(0, 150)}...` : record.description} 15 | 16 | )} 17 | {resourceDefinition.hasShow && } 18 | {resourceDefinition.hasEdit && } 19 | 20 | ); 21 | }; 22 | 23 | export default DefaultPopupContent; 24 | -------------------------------------------------------------------------------- /src/frontend/packages/geo-components/src/MapList/QueryStringUpdater.js: -------------------------------------------------------------------------------- 1 | import { useMapEvents } from 'react-leaflet'; 2 | import { useSearchParams } from 'react-router-dom'; 3 | 4 | // Keep the zoom and center in query string, so that when we navigate back to the page, it stays focused on the same area 5 | const QueryStringUpdater = () => { 6 | const [searchParams, setSearchParams] = useSearchParams(); 7 | 8 | useMapEvents({ 9 | moveend: test => { 10 | setSearchParams(params => ({ 11 | ...Object.fromEntries(params), 12 | lat: test.target.getCenter().lat, 13 | lng: test.target.getCenter().lng, 14 | zoom: test.target.getZoom() 15 | })); 16 | }, 17 | zoomend: test => { 18 | setSearchParams(params => ({ 19 | ...Object.fromEntries(params), 20 | zoom: test.target.getZoom() 21 | })); 22 | } 23 | }); 24 | 25 | return null; 26 | }; 27 | 28 | export default QueryStringUpdater; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/geo-components/src/extractContext.js: -------------------------------------------------------------------------------- 1 | const extractContext = (context, key) => { 2 | const property = context.find(property => property.id.startsWith(`${key}.`)); 3 | if (property) return property.text; 4 | }; 5 | 6 | export default extractContext; 7 | -------------------------------------------------------------------------------- /src/frontend/packages/geo-components/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as extractContext } from './extractContext'; 2 | export { default as LocationInput } from './LocationInput'; 3 | export { default as MapList } from './MapList/MapList'; 4 | export { default as MapField } from './MapField/MapField'; 5 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin input components for SemApps 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/input-components). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from 'react'; 2 | import { ImageInputProps } from 'react-admin'; 3 | import { JSX } from 'react/jsx-runtime'; 4 | export const ImageInput: FunctionComponent; 5 | export function MultiServerAutocompleteArrayInput({ 6 | optionText, 7 | ...rest 8 | }: { 9 | [x: string]: any; 10 | optionText: any; 11 | }): JSX.Element; 12 | export function MultiServerAutocompleteInput({ 13 | optionText, 14 | ...rest 15 | }: { 16 | [x: string]: any; 17 | optionText: any; 18 | }): JSX.Element; 19 | export function MultiLinesInput(props: any): JSX.Element; 20 | export function ReferenceArrayInput(props: any): JSX.Element | null; 21 | export function ReferenceInput({ children, ...rest }: { [x: string]: any; children: any }): JSX.Element; 22 | 23 | //# sourceMappingURL=index.d.ts.map 24 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/input-components", 3 | "version": "1.1.3", 4 | "description": "React-Admin input components for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "source": "src/index.ts", 8 | "main": "dist/index.cjs.js", 9 | "module": "dist/index.es.js", 10 | "files": [ 11 | "dist" 12 | ], 13 | "scripts": { 14 | "build": "parcel build --no-cache && yalc publish --push --changed", 15 | "watch": "nodemon --ext ts,tsx,js --watch src --exec 'yarn build'" 16 | }, 17 | "dependencies": { 18 | "@semapps/semantic-data-provider": "1.1.3" 19 | }, 20 | "peerDependencies": { 21 | "react": "^18.2.0", 22 | "react-admin": "^4.11.0", 23 | "react-hook-form": "^7.43.9" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "types": "dist/index.d.ts" 29 | } 30 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/MultiLinesInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TextInput } from 'react-admin'; 3 | 4 | const MultiLinesInput = props => ( 5 | (value ? (Array.isArray(value) ? value.join('\n') : value) : '')} 9 | parse={value => value.split(/\r?\n/)} 10 | {...props} 11 | /> 12 | ); 13 | 14 | export default MultiLinesInput; 15 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/MultiServerAutocompleteArrayInput.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react'; 2 | import { AutocompleteArrayInput } from 'react-admin'; 3 | import { useDataServers } from '@semapps/semantic-data-provider'; 4 | import OptionRenderer from './OptionRenderer'; 5 | 6 | const MultiServerAutocompleteArrayInput = ({ optionText, ...rest }) => { 7 | const dataServers = useDataServers(); 8 | const matchSuggestion = useCallback( 9 | (filterValue, choice) => choice[optionText].toLowerCase().match(filterValue.toLowerCase()), 10 | [optionText] 11 | ); 12 | return ( 13 | } 16 | inputText={choice => choice[optionText]} 17 | {...rest} 18 | /> 19 | ); 20 | }; 21 | 22 | export default MultiServerAutocompleteArrayInput; 23 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/MultiServerAutocompleteInput.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react'; 2 | import { AutocompleteInput } from 'react-admin'; 3 | import { useDataServers } from '@semapps/semantic-data-provider'; 4 | 5 | const MultiServerAutocompleteInput = ({ optionText, ...rest }) => { 6 | const dataServers = useDataServers(); 7 | // We cannot use OptionRenderer like MultiServerAutocompleteArrayInput because there is a bug with AutocompleteInput 8 | const optionTextWithServerName = useCallback( 9 | record => { 10 | if (record && dataServers) { 11 | const server = Object.values(dataServers).find(server => record.id.startsWith(server.baseUrl)); 12 | return record[optionText] + (server ? ` (${server.name})` : ''); 13 | } 14 | }, 15 | [optionText, dataServers] 16 | ); 17 | return ; 18 | }; 19 | 20 | export default MultiServerAutocompleteInput; 21 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/OptionRenderer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useRecordContext } from 'react-admin'; 3 | 4 | const OptionRenderer = ({ optionText, dataServers }) => { 5 | const record = useRecordContext(); 6 | const server = dataServers && Object.values(dataServers).find(server => record.id.startsWith(server.baseUrl)); 7 | return ( 8 | 9 | {record[optionText]} 10 | {server && ( 11 | 12 |  ({server.name}) 13 | 14 | )} 15 | 16 | ); 17 | }; 18 | 19 | export default OptionRenderer; 20 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/ReferenceArrayInput.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { ReferenceArrayInput as RaReferenceArrayInput } from 'react-admin'; 3 | import { useController } from 'react-hook-form'; 4 | 5 | const ReferenceArrayInput = props => { 6 | const { 7 | field: { value, onChange } 8 | } = useController({ name: props.source }); 9 | 10 | useEffect(() => { 11 | if (value && !Array.isArray(value)) { 12 | onChange([value]); 13 | } 14 | }, [value, onChange]); 15 | 16 | // Wait for change to be effective before rendering component 17 | // Otherwise it will be wrongly initialized and it won't work 18 | if (value && !Array.isArray(value)) return null; 19 | 20 | return ; 21 | }; 22 | 23 | export default ReferenceArrayInput; 24 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/ReferenceInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ReferenceInput as RaReferenceInput } from 'react-admin'; 3 | 4 | const format = value => { 5 | // If there is no value, return immediately 6 | if (!value) return value; 7 | // If the value is an object with an @id field, return the uri 8 | return typeof value === 'object' ? value.id || value['@id'] : value; 9 | }; 10 | 11 | const ReferenceInput = ({ children, ...rest }) => { 12 | const child = React.Children.only(children); 13 | return {React.cloneElement(child, { format })}; 14 | }; 15 | 16 | export default ReferenceInput; 17 | -------------------------------------------------------------------------------- /src/frontend/packages/input-components/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ImageInput } from './ImageInput'; 2 | export { default as MultiServerAutocompleteArrayInput } from './MultiServerAutocompleteArrayInput'; 3 | export { default as MultiServerAutocompleteInput } from './MultiServerAutocompleteInput'; 4 | export { default as MultiLinesInput } from './MultiLinesInput'; 5 | export { default as ReferenceArrayInput } from './ReferenceArrayInput'; 6 | export { default as ReferenceInput } from './ReferenceInput'; 7 | -------------------------------------------------------------------------------- /src/frontend/packages/interop-components/README.md: -------------------------------------------------------------------------------- 1 | # Interoperability components 2 | 3 | React-Admin components to handle interoperability between SemApps instances 4 | 5 | ## Documentation 6 | 7 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/interop-components). 8 | 9 | ## Development 10 | 11 | ### `yarn run build` 12 | 13 | Build the library in CommonJS and ES mode. 14 | This command should always be run before publishing. 15 | 16 | ### `yarn run watch` 17 | 18 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 19 | -------------------------------------------------------------------------------- /src/frontend/packages/interop-components/src/fetch/fetchESCO.js: -------------------------------------------------------------------------------- 1 | import urlJoin from 'url-join'; 2 | import StarBorderIcon from '@mui/icons-material/StarBorder'; 3 | 4 | const capitalize = s => (s && s[0].toUpperCase() + s.slice(1)) || ''; 5 | 6 | const fetchESCO = 7 | (apiUrl = 'https://ec.europa.eu/esco/api', type = 'skill') => 8 | async ({ keyword, locale }) => { 9 | const response = await fetch( 10 | urlJoin( 11 | apiUrl, 12 | `suggest2?text=${encodeURIComponent( 13 | keyword 14 | )}&language=${locale}&type=${type}&isInScheme=&facet=&offset=&limit=&full=&selectedVersion=&viewObsolete=` 15 | ) 16 | ); 17 | if (response.ok) { 18 | const json = await response.json(); 19 | return json._embedded.results.map(r => ({ 20 | uri: r.uri, 21 | label: capitalize(r.title.replace('’', "'")), 22 | icon: StarBorderIcon 23 | })); 24 | } 25 | throw new Error('Failed to fetch ESCO server'); 26 | }; 27 | 28 | export default fetchESCO; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/interop-components/src/fetch/fetchWikidata.js: -------------------------------------------------------------------------------- 1 | import LanguageIcon from '@mui/icons-material/Language'; 2 | 3 | const capitalize = s => (s && s[0].toUpperCase() + s.slice(1)) || ''; 4 | 5 | const fetchWikidata = 6 | (apiUrl = 'https://www.wikidata.org/w/api.php') => 7 | async ({ keyword, locale }) => { 8 | const response = await fetch( 9 | `${apiUrl}?action=wbsearchentities&format=json&language=${locale}&uselang=${locale}&type=item&limit=10&origin=*&search=${encodeURIComponent( 10 | keyword 11 | )}` 12 | ); 13 | if (response.ok) { 14 | const json = await response.json(); 15 | return json.search.map(r => ({ 16 | uri: r.concepturi, 17 | label: capitalize(r.match.text), 18 | summary: capitalize(r.description), 19 | icon: LanguageIcon 20 | })); 21 | } 22 | throw new Error('Failed to fetch Wikidata server'); 23 | }; 24 | 25 | export default fetchWikidata; 26 | -------------------------------------------------------------------------------- /src/frontend/packages/interop-components/src/hooks/useSync.js: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { useNotify, useDataProvider, useRedirect } from 'react-admin'; 3 | 4 | const useSync = resourceId => { 5 | const dataProvider = useDataProvider(); 6 | const notify = useNotify(); 7 | const redirect = useRedirect(); 8 | 9 | return useCallback( 10 | async remoteRecordUri => { 11 | await dataProvider.create(resourceId, { id: remoteRecordUri }); 12 | 13 | redirect(`/${resourceId}/${encodeURIComponent(remoteRecordUri)}/show`); 14 | notify('La ressource a bien été importée', { type: 'success' }); 15 | }, 16 | [dataProvider, redirect, notify] 17 | ); 18 | }; 19 | 20 | export default useSync; 21 | -------------------------------------------------------------------------------- /src/frontend/packages/interop-components/src/index.ts: -------------------------------------------------------------------------------- 1 | // Dialogs 2 | export { default as LexiconCreateDialog } from './dialogs/LexiconCreateDialog'; 3 | 4 | // Forms 5 | export { default as CreateOrImportForm } from './forms/CreateOrImportForm'; 6 | export { default as ImportForm } from './forms/ImportForm'; 7 | export { default as LexiconImportForm } from './forms/LexiconImportForm'; 8 | 9 | // Inputs 10 | export { default as LexiconAutocompleteInput } from './inputs/LexiconAutocompleteInput'; 11 | 12 | // Fetch 13 | export { default as fetchWikidata } from './fetch/fetchWikidata'; 14 | export { default as fetchESCO } from './fetch/fetchESCO'; 15 | 16 | // Hooks 17 | export { default as useFork } from './hooks/useFork'; 18 | export { default as useSync } from './hooks/useSync'; 19 | -------------------------------------------------------------------------------- /src/frontend/packages/list-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin list components for SemApps 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/list-components). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/list-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/list-components", 3 | "version": "1.1.3", 4 | "description": "React-Admin list components for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "source": "src/index.ts", 8 | "main": "dist/index.cjs.js", 9 | "module": "dist/index.es.js", 10 | "types": "dist/index.d.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "tsc && parcel build && yalc publish --push --changed", 16 | "watch": "nodemon --ext ts,tsx,js --watch src --exec 'yarn build'" 17 | }, 18 | "dependencies": { 19 | "@semapps/semantic-data-provider": "1.1.3", 20 | "react-masonry-css": "^1.0.14" 21 | }, 22 | "peerDependencies": { 23 | "@mui/icons-material": "^5.13.1", 24 | "@mui/material": "^5.13.1", 25 | "@mui/styles": "^5.13.1", 26 | "react": "^18.2.0", 27 | "react-admin": "^4.11.0", 28 | "react-router": "^6.1.0" 29 | }, 30 | "publishConfig": { 31 | "access": "public" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/frontend/packages/list-components/src/MultiViewsList/ListViewContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ListViewContext = React.createContext({ views: null, currentView: null, setView: () => null }); 4 | 5 | export default ListViewContext; 6 | -------------------------------------------------------------------------------- /src/frontend/packages/list-components/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ChipList } from './ChipList'; 2 | export { default as GridList } from './GridList'; 3 | export { default as MasonryList } from './MasonryList'; 4 | export { default as ReferenceFilter } from './ReferenceFilter'; 5 | 6 | export { default as MultiViewsList } from './MultiViewsList/MultiViewsList'; 7 | export { default as ListActionsWithViews } from './MultiViewsList/ListActionsWithViews'; 8 | export { default as ListViewContext } from './MultiViewsList/ListViewContext'; 9 | export { default as ViewsButtons } from './MultiViewsList/ViewsButtons'; 10 | -------------------------------------------------------------------------------- /src/frontend/packages/markdown-components/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin components for markdown display and input 2 | 3 | ## Documentation 4 | 5 | See the [dedicated page on the SemApps website](https://semapps.org/docs/frontend/markdown-components). 6 | 7 | ## Development 8 | 9 | ### `yarn run build` 10 | 11 | Build the library in CommonJS and ES mode. 12 | This command should always be run before publishing. 13 | 14 | ### `yarn run watch` 15 | 16 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 17 | -------------------------------------------------------------------------------- /src/frontend/packages/markdown-components/dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { FunctionComponent } from 'react'; 2 | import { ReactMdeProps } from 'react-mde'; 3 | import { MarkdownToJSX } from 'markdown-to-jsx'; 4 | import { TextInputProps } from 'react-admin'; 5 | export function MarkdownField({ 6 | source, 7 | LabelComponent, 8 | overrides, 9 | ...rest 10 | }: { 11 | [x: string]: any; 12 | source: any; 13 | LabelComponent?: string | undefined; 14 | overrides?: {} | undefined; 15 | }): import('react/jsx-runtime').JSX.Element | null; 16 | type Props = TextInputProps & { 17 | overrides?: MarkdownToJSX.Overrides; 18 | reactMdeProps?: ReactMdeProps; 19 | }; 20 | export const MarkdownInput: FunctionComponent; 21 | export function useLoadLinks( 22 | resourceType: any, 23 | labelProp: any 24 | ): (keyword: any) => Promise< 25 | { 26 | preview: any; 27 | value: string; 28 | }[] 29 | >; 30 | 31 | //# sourceMappingURL=index.d.ts.map 32 | -------------------------------------------------------------------------------- /src/frontend/packages/markdown-components/dist/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"mappings":";;;;AAKA;;;;;mDA4BC;ACyDD,aAAa,cAAc,GAAG;IAC5B,SAAS,CAAC,EAAE,cAAc,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,CAAC;AAEF,OAAA,MAAM,eAAe,kBAAkB,KAAK,CA6C3C,CAAC;AC1IF;;;KAsBC","sources":["packages/markdown-components/src/src/MarkdownField.js","packages/markdown-components/src/src/MarkdownInput.tsx","packages/markdown-components/src/src/useLoadLinks.js","packages/markdown-components/src/src/index.ts","packages/markdown-components/src/index.ts"],"sourcesContent":[null,null,null,null,"export { default as MarkdownField } from './MarkdownField';\nexport { default as MarkdownInput } from './MarkdownInput';\nexport { default as useLoadLinks } from './useLoadLinks';\n"],"names":[],"version":3,"file":"index.d.ts.map"} -------------------------------------------------------------------------------- /src/frontend/packages/markdown-components/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as MarkdownField } from './MarkdownField'; 2 | export { default as MarkdownInput } from './MarkdownInput'; 3 | export { default as useLoadLinks } from './useLoadLinks'; 4 | -------------------------------------------------------------------------------- /src/frontend/packages/markdown-components/src/useLoadLinks.js: -------------------------------------------------------------------------------- 1 | import { useDataProvider, useTranslate } from 'react-admin'; 2 | 3 | const useLoadLinks = (resourceType, labelProp) => { 4 | const dataProvider = useDataProvider(); 5 | const translate = useTranslate(); 6 | return async keyword => { 7 | if (keyword) { 8 | const results = await dataProvider.getList(resourceType, { 9 | pagination: { 10 | page: 1, 11 | perPage: 5 12 | }, 13 | filter: { q: keyword } 14 | }); 15 | if (results.total > 0) { 16 | return results.data.map(record => ({ 17 | preview: record[labelProp], 18 | value: `[${record[labelProp]}](/${resourceType}/${encodeURIComponent(record.id)}/show)` 19 | })); 20 | } 21 | return [{ preview: translate('ra.navigation.no_results'), value: `[${keyword}` }]; 22 | } 23 | return [{ preview: translate('ra.action.search'), value: `[${keyword}` }]; 24 | }; 25 | }; 26 | 27 | export default useLoadLinks; 28 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/README.md: -------------------------------------------------------------------------------- 1 | # React-Admin data provider for LDP servers 2 | 3 | ## Commands 4 | 5 | ### `yarn run build` 6 | 7 | Build the library in CommonJS and ES mode. 8 | This command should always be run before publishing. 9 | 10 | ### `yarn run watch` 11 | 12 | Develop mode. Any change you make to a file in the `/src` directory will be immediately compiled. 13 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/delete.ts: -------------------------------------------------------------------------------- 1 | import { DeleteParams, RaRecord } from 'react-admin'; 2 | import { Configuration } from '../types'; 3 | 4 | const deleteMethod = (config: Configuration) => async (resourceId: string, params: DeleteParams) => { 5 | const { httpClient } = config; 6 | 7 | await httpClient(`${params.id}`, { 8 | method: 'DELETE' 9 | }); 10 | 11 | return { data: { id: params.id } }; 12 | }; 13 | 14 | export default deleteMethod; 15 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/deleteMany.js: -------------------------------------------------------------------------------- 1 | const deleteManyMethod = config => async (resourceId, params) => { 2 | const { httpClient } = config; 3 | const ids = []; 4 | 5 | for (const id of params.ids) { 6 | try { 7 | await httpClient(id, { 8 | method: 'DELETE' 9 | }); 10 | ids.push(id); 11 | } catch (e) { 12 | // Do nothing if we fail to delete a resource 13 | } 14 | } 15 | 16 | return { data: ids }; 17 | }; 18 | 19 | export default deleteManyMethod; 20 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/getDataModels.js: -------------------------------------------------------------------------------- 1 | const getDataModels = config => () => { 2 | return config.resources; 3 | }; 4 | 5 | export default getDataModels; 6 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/getDataServers.js: -------------------------------------------------------------------------------- 1 | const getDataServers = config => () => { 2 | return config.dataServers; 3 | }; 4 | 5 | export default getDataServers; 6 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/getMany.js: -------------------------------------------------------------------------------- 1 | import getOne from './getOne'; 2 | 3 | const getManyMethod = config => async (resourceId, params) => { 4 | const { returnFailedResources } = config; 5 | 6 | let returnData = await Promise.all( 7 | params.ids.map(id => 8 | getOne(config)(resourceId, { id: typeof id === 'object' ? id['@id'] : id }) 9 | .then(({ data }) => data) 10 | .catch(() => { 11 | // Catch if one resource fails to load 12 | // Otherwise no references will be show if only one is missing 13 | // See https://github.com/marmelab/react-admin/issues/5190 14 | if (returnFailedResources) { 15 | return { id, _error: true }; 16 | } 17 | // Returning nothing 18 | }) 19 | ) 20 | ); 21 | 22 | // We don't want undefined results to appear in the results as it will break with react-admin 23 | returnData = returnData.filter(e => e); 24 | 25 | return { data: returnData }; 26 | }; 27 | 28 | export default getManyMethod; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/getManyReference.js: -------------------------------------------------------------------------------- 1 | import getList from './getList'; 2 | 3 | const getManyReferenceMethod = config => async (resourceId, params) => { 4 | params.filter = { ...params.filter, [params.target]: params.id }; 5 | delete params.target; 6 | return await getList(config)(resourceId, params); 7 | }; 8 | 9 | export default getManyReferenceMethod; 10 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/methods/update.ts: -------------------------------------------------------------------------------- 1 | import { RaRecord, UpdateParams } from 'react-admin'; 2 | import { Configuration } from '../types'; 3 | import handleFiles from '../utils/handleFiles'; 4 | import getServerKeyFromUri from '../utils/getServerKeyFromUri'; 5 | 6 | const updateMethod = (config: Configuration) => async (resourceId: string, params: UpdateParams) => { 7 | const { httpClient, jsonContext, dataServers } = config; 8 | 9 | const serverKey = getServerKeyFromUri(params.id, dataServers); 10 | 11 | // Upload files, if there are any 12 | const { updatedRecord } = await handleFiles.upload(params.data, config, serverKey); 13 | params.data = updatedRecord; 14 | 15 | await httpClient(`${params.id}`, { 16 | method: 'PUT', 17 | body: JSON.stringify({ 18 | '@context': jsonContext, 19 | ...params.data 20 | }) 21 | }); 22 | 23 | return { data: params.data }; 24 | }; 25 | 26 | export default updateMethod; 27 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/arrayOf.ts: -------------------------------------------------------------------------------- 1 | const arrayOf = (value: T | T[]): T[] => { 2 | // If the field is null-ish, we suppose there are no values. 3 | if (!value) { 4 | return []; 5 | } 6 | // Return as is. 7 | if (Array.isArray(value)) { 8 | return value; 9 | } 10 | // Single value is made an array. 11 | return [value]; 12 | }; 13 | 14 | export default arrayOf; 15 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/compactPredicate.ts: -------------------------------------------------------------------------------- 1 | import jsonld, { ContextDefinition } from 'jsonld'; 2 | 3 | const compactPredicate = async ( 4 | predicate: string, 5 | context: string | string[] | Record 6 | ): Promise => { 7 | const result = await jsonld.compact({ [predicate]: '' }, context as ContextDefinition); 8 | 9 | return Object.keys(result).find(key => key !== '@context')!; 10 | }; 11 | 12 | export default compactPredicate; 13 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/expandTypes.ts: -------------------------------------------------------------------------------- 1 | import jsonld from 'jsonld'; 2 | import arrayOf from './arrayOf'; 3 | 4 | const isURI = (value: any) => 5 | (typeof value === 'string' || value instanceof String) && (value.startsWith('http') || value.startsWith('urn:')); 6 | 7 | const expandTypes = async (types: string[], context: any): Promise => { 8 | // If types are already full URIs, return them immediately 9 | if (types.every(type => isURI(type))) return types; 10 | 11 | const result = await jsonld.expand({ '@context': context, '@type': types }); 12 | 13 | const expandedTypes = arrayOf(result[0]['@type']!); 14 | 15 | if (!expandedTypes.every(type => isURI(type))) { 16 | throw new Error(` 17 | Could not expand all types (${expandedTypes.join(', ')}). 18 | Is an ontology missing or not registered yet on the local context ? 19 | `); 20 | } 21 | 22 | return expandedTypes; 23 | }; 24 | 25 | export default expandTypes; 26 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/fetchResource.js: -------------------------------------------------------------------------------- 1 | import jsonld from 'jsonld'; 2 | 3 | const fetchResource = async (resourceUri, config) => { 4 | const { httpClient, jsonContext } = config; 5 | 6 | let { json: data } = await httpClient(resourceUri); 7 | 8 | if (!data) throw new Error(`Not a valid JSON: ${resourceUri}`); 9 | 10 | data.id = data.id || data['@id']; 11 | 12 | // We compact only if the context is different between the frontend and the middleware 13 | // TODO deep compare if the context is an object 14 | if (data['@context'] !== jsonContext) { 15 | data = await jsonld.compact(data, jsonContext); 16 | } 17 | 18 | return data; 19 | }; 20 | 21 | export default fetchResource; 22 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/findContainersWithShapeTree.ts: -------------------------------------------------------------------------------- 1 | import { DataServersConfig, Container } from '../types'; 2 | import parseServerKeys from './parseServerKeys'; 3 | 4 | /** 5 | * Return all containers matching the given shape tree 6 | */ 7 | const findContainersWithShapeTree = ( 8 | shapeTreeUri: string, 9 | serverKeys: string | string[] | undefined, 10 | dataServers: DataServersConfig 11 | ) => { 12 | const matchingContainers: Container[] = []; 13 | 14 | const parsedServerKeys = parseServerKeys(serverKeys || '@all', dataServers); 15 | 16 | Object.keys(dataServers).forEach(dataServerKey => { 17 | if (parsedServerKeys.includes(dataServerKey)) { 18 | dataServers[dataServerKey].containers?.forEach(container => { 19 | if (container.shapeTreeUri === shapeTreeUri) { 20 | matchingContainers.push(container); 21 | } 22 | }); 23 | } 24 | }); 25 | 26 | return matchingContainers; 27 | }; 28 | 29 | export default findContainersWithShapeTree; 30 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/findContainersWithTypes.ts: -------------------------------------------------------------------------------- 1 | import { DataServersConfig, Container } from '../types'; 2 | import parseServerKeys from './parseServerKeys'; 3 | 4 | /** 5 | * Return all containers matching the given types 6 | */ 7 | const findContainersWithTypes = ( 8 | types: string[], 9 | serverKeys: string | string[] | undefined, 10 | dataServers: DataServersConfig 11 | ) => { 12 | const matchingContainers: Container[] = []; 13 | 14 | const parsedServerKeys = parseServerKeys(serverKeys || '@all', dataServers); 15 | 16 | Object.keys(dataServers).forEach(dataServerKey => { 17 | if (parsedServerKeys.includes(dataServerKey)) { 18 | dataServers[dataServerKey].containers?.forEach(container => { 19 | if (container.types?.some(t => types.includes(t))) { 20 | matchingContainers.push(container); 21 | } 22 | }); 23 | } 24 | }); 25 | 26 | return matchingContainers; 27 | }; 28 | 29 | export default findContainersWithTypes; 30 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/findContainersWithURIs.ts: -------------------------------------------------------------------------------- 1 | import { DataServersConfig, Container } from '../types'; 2 | 3 | const findContainersWithURIs = (containersUris: string[], dataServers: DataServersConfig) => { 4 | const matchingContainers: Container[] = []; 5 | 6 | Object.keys(dataServers).forEach(serverKey => { 7 | dataServers[serverKey].containers?.forEach(container => { 8 | if (container.uri && containersUris.includes(container.uri)) { 9 | matchingContainers.push(container); 10 | } 11 | }); 12 | }); 13 | 14 | return matchingContainers; 15 | }; 16 | 17 | export default findContainersWithURIs; 18 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getEmbedFrame.js: -------------------------------------------------------------------------------- 1 | const getEmbedFrame = blankNodes => { 2 | let embedFrame = {}; 3 | let predicates; 4 | if (blankNodes) { 5 | for (const blankNode of blankNodes) { 6 | if (blankNode.includes('/')) { 7 | predicates = blankNode.split('/').reverse(); 8 | } else { 9 | predicates = [blankNode]; 10 | } 11 | embedFrame = { 12 | ...embedFrame, 13 | ...predicates.reduce( 14 | (accumulator, predicate) => ({ 15 | [predicate]: { 16 | '@embed': '@last', 17 | ...accumulator 18 | } 19 | }), 20 | {} 21 | ) 22 | }; 23 | } 24 | return embedFrame; 25 | } 26 | }; 27 | 28 | export default getEmbedFrame; 29 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getPrefixFromUri.ts: -------------------------------------------------------------------------------- 1 | const getPrefixFromUri = (uri: string, ontologies: Record) => { 2 | for (const [prefix, namespace] of Object.entries(ontologies)) { 3 | if (uri.startsWith(namespace)) return uri.replace(namespace, `${prefix}:`); 4 | } 5 | return uri; 6 | }; 7 | 8 | export default getPrefixFromUri; 9 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getRdfPrefixes.js: -------------------------------------------------------------------------------- 1 | const getRdfPrefixes = ontologies => { 2 | return Object.entries(ontologies) 3 | .map(([prefix, url]) => `PREFIX ${prefix}: <${url}>`) 4 | .join('\n'); 5 | }; 6 | 7 | export default getRdfPrefixes; 8 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getServerKeyFromType.js: -------------------------------------------------------------------------------- 1 | const getServerKeyFromType = (type, dataServers) => { 2 | return ( 3 | dataServers && 4 | Object.keys(dataServers).find(key => { 5 | return dataServers[key][type]; 6 | }) 7 | ); 8 | }; 9 | 10 | export default getServerKeyFromType; 11 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getServerKeyFromUri.js: -------------------------------------------------------------------------------- 1 | // Return the first server matching with the baseUrl 2 | const getServerKeyFromUri = (uri, dataServers) => { 3 | if (!uri) throw Error(`No URI provided to getServerKeyFromUri`); 4 | return ( 5 | dataServers && 6 | Object.keys(dataServers).find(key => { 7 | if (dataServers[key].pod) { 8 | // The baseUrl ends with /data so remove this part to match with the webId and webId-related URLs (/inbox, /outbox...) 9 | return dataServers[key].baseUrl && uri.startsWith(dataServers[key].baseUrl.replace('/data', '')); 10 | } 11 | return uri.startsWith(dataServers[key].baseUrl); 12 | }) 13 | ); 14 | }; 15 | 16 | export default getServerKeyFromUri; 17 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getUploadsContainerUri.ts: -------------------------------------------------------------------------------- 1 | import { Configuration } from '../types'; 2 | 3 | const getUploadsContainerUri = (config: Configuration, serverKey?: string) => { 4 | // If no server key is defined or if the server has no uploads container, find any server with a uploads container 5 | if ( 6 | !serverKey || 7 | !config.dataServers[serverKey].containers || 8 | !config.dataServers[serverKey].containers?.find(c => c.binaryResources) 9 | ) { 10 | serverKey = Object.keys(config.dataServers).find( 11 | key => config.dataServers[key].containers?.find(c => c.binaryResources) 12 | ); 13 | } 14 | 15 | if (serverKey) { 16 | return config.dataServers[serverKey].containers?.find(c => c.binaryResources)?.uri; 17 | } else { 18 | // No server has an uploads container 19 | return null; 20 | } 21 | }; 22 | 23 | export default getUploadsContainerUri; 24 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/dataProvider/utils/getUriFromPrefix.ts: -------------------------------------------------------------------------------- 1 | const getUriFromPrefix = (item: string, ontologies: Record) => { 2 | if (item.startsWith('http://') || item.startsWith('https://')) { 3 | // Already resolved, return the URI 4 | return item; 5 | } else if (item === 'a') { 6 | // Special case 7 | return 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; 8 | } else { 9 | const [prefix, value] = item.split(':'); 10 | if (value) { 11 | if (ontologies[prefix]) { 12 | return ontologies[prefix] + value; 13 | } else { 14 | throw new Error(`No ontology found with prefix ${prefix}`); 15 | } 16 | } else { 17 | throw new Error(`The value "${item}" is not correct. It must include a prefix or be a full URI.`); 18 | } 19 | } 20 | }; 21 | 22 | export default getUriFromPrefix; 23 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useCompactPredicate.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import useDataProviderConfig from './useDataProviderConfig'; 3 | import compactPredicate from '../dataProvider/utils/compactPredicate'; 4 | 5 | const useCompactPredicate = ( 6 | predicate: string, 7 | context?: string | string[] | Record 8 | ): string | undefined => { 9 | const config = useDataProviderConfig(); 10 | const [result, setResult] = useState(); 11 | 12 | useEffect(() => { 13 | if (config && predicate) { 14 | compactPredicate(predicate, context || config.jsonContext).then(r => { 15 | setResult(r); 16 | }); 17 | } 18 | }, [predicate, setResult, config, context]); 19 | 20 | return result; 21 | }; 22 | 23 | export default useCompactPredicate; 24 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useContainerByUri.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import useDataServers from './useDataServers'; 3 | import { Container } from '../dataProvider/types'; 4 | 5 | const useContainerByUri = (containerUri: string) => { 6 | const dataServers = useDataServers(); 7 | const [container, setContainer] = useState(); 8 | 9 | useEffect(() => { 10 | if (dataServers && containerUri) { 11 | Object.keys(dataServers).forEach(serverKey => { 12 | dataServers[serverKey].containers?.forEach(c => { 13 | if (c.uri === containerUri) { 14 | setContainer(c); 15 | } 16 | }); 17 | }); 18 | } 19 | }, [dataServers, setContainer, containerUri]); 20 | 21 | return container; 22 | }; 23 | 24 | export default useContainerByUri; 25 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useCreateContainerUri.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | import useGetCreateContainerUri from './useGetCreateContainerUri'; 3 | 4 | const useCreateContainerUri = (resourceId: string) => { 5 | const getCreateContainerUri = useGetCreateContainerUri(); 6 | 7 | const createContainerUri = useMemo(() => getCreateContainerUri(resourceId), [getCreateContainerUri, resourceId]); 8 | 9 | return createContainerUri; 10 | }; 11 | 12 | export default useCreateContainerUri; 13 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useDataModel.ts: -------------------------------------------------------------------------------- 1 | import useDataProviderConfig from './useDataProviderConfig'; 2 | 3 | const useDataModel = (resourceId: string) => { 4 | const config = useDataProviderConfig(); 5 | return config?.resources[resourceId]; 6 | }; 7 | 8 | export default useDataModel; 9 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useDataModels.ts: -------------------------------------------------------------------------------- 1 | import useDataProviderConfig from './useDataProviderConfig'; 2 | 3 | const useDataModels = () => { 4 | const config = useDataProviderConfig(); 5 | return config?.resources; 6 | }; 7 | 8 | export default useDataModels; 9 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useDataProviderConfig.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | import { useDataProvider } from 'react-admin'; 3 | import { Configuration, SemanticDataProvider } from '../dataProvider/types'; 4 | 5 | const useDataProviderConfig = (): Configuration | undefined => { 6 | const dataProvider = useDataProvider(); 7 | const [config, setConfig] = useState(); 8 | const [isLoading, setIsLoading] = useState(false); 9 | 10 | useEffect(() => { 11 | if (!isLoading && !config) { 12 | setIsLoading(true); 13 | dataProvider.getConfig().then(c => { 14 | setConfig(c); 15 | setIsLoading(false); 16 | }); 17 | } 18 | }, [dataProvider, setConfig, config, setIsLoading, isLoading]); 19 | 20 | return config; 21 | }; 22 | 23 | export default useDataProviderConfig; 24 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useDataServers.ts: -------------------------------------------------------------------------------- 1 | import useDataProviderConfig from './useDataProviderConfig'; 2 | 3 | const useDataServers = () => { 4 | const config = useDataProviderConfig(); 5 | return config?.dataServers; 6 | }; 7 | 8 | export default useDataServers; 9 | -------------------------------------------------------------------------------- /src/frontend/packages/semantic-data-provider/src/hooks/useGetPrefixFromUri.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import useDataProviderConfig from './useDataProviderConfig'; 3 | import getPrefixFromUri from '../dataProvider/utils/getPrefixFromUri'; 4 | 5 | const useGetPrefixFromUri = () => { 6 | const config = useDataProviderConfig(); 7 | 8 | return useCallback((uri: string) => getPrefixFromUri(uri, config!.ontologies), [config?.ontologies]); 9 | }; 10 | 11 | export default useGetPrefixFromUri; 12 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js", 3 | "globals": { 4 | "process": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/README.md: -------------------------------------------------------------------------------- 1 | # Data Management System template 2 | 3 | See [this guide](https://semapps.org/docs/guides/dms) for information. 4 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/cra-template-dms", 3 | "version": "1.1.3", 4 | "description": "DMS REACT template for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "main": "template.json", 11 | "keywords": [ 12 | "react", 13 | "create-react-app", 14 | "template", 15 | "typescript" 16 | ], 17 | "files": [ 18 | "template", 19 | "template.json" 20 | ], 21 | "engines": { 22 | "node": ">=10" 23 | }, 24 | "gitHead": "4fa70690c5932b8c9d9cb5eb4c36a10f687703ff", 25 | "dependencies": { 26 | "@semapps/semantic-data-provider": "1.1.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "dependencies": { 4 | "@semapps/semantic-data-provider": "0.4.0-alpha.38", 5 | "react": "^16.13.1", 6 | "react-admin": "^4.11.0", 7 | "react-dom": "^16.13.1", 8 | "react-scripts": "3.4.0" 9 | }, 10 | "scripts": { 11 | "start": "react-scripts start", 12 | "build": "react-scripts build", 13 | "eject": "react-scripts eject" 14 | }, 15 | "eslintConfig": { 16 | "extends": "react-app" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/.env: -------------------------------------------------------------------------------- 1 | REACT_APP_MIDDLEWARE_URL=http://localhost:3000/ 2 | PORT=5000 3 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/README.md: -------------------------------------------------------------------------------- 1 | # Data Management System template 2 | 3 | See [this guide](https://semapps.org/docs/guides/dms) for information. 4 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/frontend/templates/cra-template-dms/template/gitignore -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/frontend/templates/cra-template-dms/template/public/favicon.ico -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | Data management system 15 | 16 | 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/frontend/templates/cra-template-dms/template/public/logo192.png -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/frontend/templates/cra-template-dms/template/public/logo512.png -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data Management System", 3 | "name": "Data Management System", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Admin, Resource } from 'react-admin'; 3 | import dataProvider from './config/dataProvider'; 4 | import { NoteList, NoteEdit, NoteCreate, NoteIcon } from './resources/notes'; 5 | 6 | const App = () => ( 7 | 8 | 16 | 17 | ); 18 | 19 | export default App; 20 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/config/dataProvider.js: -------------------------------------------------------------------------------- 1 | import { dataProvider as semanticDataProvider, httpClient } from '@semapps/semantic-data-provider'; 2 | import ontologies from './ontologies.json'; 3 | import dataServers from './dataServers'; 4 | import resources from './resources'; 5 | 6 | const dataProvider = semanticDataProvider({ 7 | dataServers, 8 | httpClient, 9 | resources, 10 | ontologies, 11 | jsonContext: `${process.env.REACT_APP_MIDDLEWARE_URL}context.json` 12 | }); 13 | 14 | export default dataProvider; 15 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/config/dataServers.js: -------------------------------------------------------------------------------- 1 | const dataServers = { 2 | main: { 3 | baseUrl: process.env.REACT_APP_MIDDLEWARE_URL, 4 | default: true 5 | } 6 | }; 7 | 8 | export default dataServers; 9 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/config/ontologies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "as", 4 | "owl": "", 5 | "url": "https://www.w3.org/ns/activitystreams#" 6 | }, 7 | { 8 | "prefix": "rdf", 9 | "owl": "", 10 | "url": "http://www.w3.org/1999/02/22-rdf-syntax-ns#" 11 | }, 12 | { 13 | "prefix": "ldp", 14 | "owl": "", 15 | "url": "http://www.w3.org/ns/ldp#" 16 | }, 17 | { 18 | "prefix": "schema", 19 | "owl": "", 20 | "url": "http://schema.org/" 21 | }, 22 | { 23 | "prefix": "foaf", 24 | "owl": "", 25 | "url": "http://xmlns.com/foaf/0.1/" 26 | }, 27 | { 28 | "prefix": "pair", 29 | "owl": "", 30 | "url": "http://virtual-assembly.org/ontologies/pair#" 31 | }, 32 | { 33 | "prefix": "skos", 34 | "owl": "", 35 | "url": "http://www.w3.org/2004/02/skos/core#" 36 | } 37 | ] 38 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/config/resources.js: -------------------------------------------------------------------------------- 1 | const resources = { 2 | Note: { 3 | types: ['as:Note'] 4 | } 5 | }; 6 | 7 | export default resources; 8 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/frontend/templates/cra-template-dms/template/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /src/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true, 4 | "allowJs": true, 5 | "declaration": true, 6 | "noLib": false, 7 | "skipLibCheck": true, 8 | "sourceMap": true, 9 | "strictNullChecks": true, 10 | "isolatedModules": true, 11 | "noImplicitAny": true, 12 | "esModuleInterop": true, 13 | "jsx": "react-jsx", 14 | "lib": ["ESNext", "dom"] 15 | }, 16 | "exclude": ["node_modules", "*.es.js", "*.cjs", "*.cjs.js"] 17 | } 18 | -------------------------------------------------------------------------------- /src/jena/Makefile: -------------------------------------------------------------------------------- 1 | init-container-builder: 2 | docker buildx create --name container-builder --driver docker-container --use --bootstrap 3 | 4 | publish: 5 | export TAG=`git describe --tags --abbrev=0 | sed 's/frontend-v/v/' | sed 's/middleware-v/v/'` 6 | COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose build --push fuseki 7 | 8 | publish-latest: 9 | export TAG="latest" 10 | COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose build --push fuseki 11 | -------------------------------------------------------------------------------- /src/jena/README.md: -------------------------------------------------------------------------------- 1 | # Jena Fuseki with WAC extension 2 | 3 | Custom version of Jena Fuseki which checks WAC permissions 4 | 5 | For more information, see https://semapps.org/docs/triplestore 6 | 7 | ## Publishing 8 | 9 | To publish the `semapps/jena-fuseki-webacl` image on AMD/ARM platforms, first create the [BuildX container](https://docs.docker.com/build/building/multi-platform/#create-a-custom-builder) with this command: 10 | 11 | ``` 12 | make init-container-builder 13 | ``` 14 | 15 | Then run this command to publish the image with the current version of SemApps: 16 | 17 | ``` 18 | make publish 19 | ``` 20 | 21 | Run this command to publish the image with the "latest" tag: 22 | 23 | ``` 24 | make publish 25 | ``` 26 | -------------------------------------------------------------------------------- /src/jena/fuseki-docker/docker-delete-old-data-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | declare -a graphs=("" "Acl" "Mirror") 5 | 6 | for graph in "${graphs[@]}"; do 7 | # Go through all files in the /fuseki/configuration 8 | for filepath in /fuseki/configuration/*.ttl; do 9 | filename=$(basename -- "$filepath") 10 | 11 | # Remove .ttl extension 12 | dataset="${filename%.*}" 13 | 14 | dir="/fuseki/databases/${dataset}${graph}" 15 | 16 | if [ -d "$dir" ]; then 17 | echo "Deleting old directories from ${dir}..." 18 | cd "${dir}" 19 | find . -iname 'Data*' ! -wholename $(find . -iname 'Data*' -type d | sort -n | tail -n 1) -type d -exec rm -rf {} + 20 | else 21 | echo "Directory ${dir} does not exist, skipping..." 22 | fi 23 | done 24 | done 25 | -------------------------------------------------------------------------------- /src/jena/fuseki-docker/extra/commons-collections4-4.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/jena/fuseki-docker/extra/commons-collections4-4.4.jar -------------------------------------------------------------------------------- /src/jena/fuseki-docker/extra/jena-permissions-3.17.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/jena/fuseki-docker/extra/jena-permissions-3.17.0.jar -------------------------------------------------------------------------------- /src/jena/fuseki-docker/extra/semapps-jena-permissions-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/jena/fuseki-docker/extra/semapps-jena-permissions-1.0.0.jar -------------------------------------------------------------------------------- /src/jena/fuseki-docker/migration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "migration_mirror", 3 | "version": "0.1.0", 4 | "description": "Migrates the configuration files of jena fuseki for Dataset, to include the mirror namedGraph", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "string-template": "^1.0.0", 9 | "match-all": "^1.0.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/jena/fuseki-docker/tdbloader: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | JVM_ARGS=${JVM_ARGS:--Xmx1200M} 17 | exec java $JVM_ARGS -cp $FUSEKI_HOME/fuseki-server.jar tdb2.tdbloader $@ 18 | -------------------------------------------------------------------------------- /src/jena/permissions/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /src/jena/permissions/README.md: -------------------------------------------------------------------------------- 1 | # Permissions JAR file containing the ShiroEvaluator class for Fuseki Permissions implementation 2 | 3 | How to build the JAR file (optional, the last version is already built and present in the Docker image). 4 | 5 | ### Install maven 6 | 7 | You will need to install the Maven command-line build tool. For more information, go to Maven. If you are using Linux, check your package manager. 8 | 9 | ``` 10 | sudo apt-get install mvn 11 | ``` 12 | 13 | if you are using Homebrew 14 | 15 | ``` 16 | brew install maven 17 | ``` 18 | 19 | ### Build 20 | 21 | ``` 22 | mvn package 23 | ``` 24 | 25 | ### copy 26 | 27 | Copy the resulting jar `target/semapps-jena-permissions-1.0.0.jar` to `src/jena/fuseki-docker/extra/` 28 | -------------------------------------------------------------------------------- /src/jena/tests/.env: -------------------------------------------------------------------------------- 1 | SEMAPPS_SPARQL_ENDPOINT=http://localhost:3030/ 2 | SEMAPPS_MAIN_DATASET=testData 3 | SEMAPPS_JENA_USER=admin 4 | SEMAPPS_JENA_PASSWORD=admin 5 | -------------------------------------------------------------------------------- /src/jena/tests/config.js: -------------------------------------------------------------------------------- 1 | // Read all .env* files in the root folder and add them to process.env 2 | // See https://github.com/kerimdzhanov/dotenv-flow for more details 3 | require('dotenv-flow').config(); 4 | 5 | module.exports = { 6 | SPARQL_ENDPOINT: process.env.SEMAPPS_SPARQL_ENDPOINT, 7 | MAIN_DATASET: process.env.SEMAPPS_MAIN_DATASET, 8 | JENA_USER: process.env.SEMAPPS_JENA_USER, 9 | JENA_PASSWORD: process.env.SEMAPPS_JENA_PASSWORD 10 | }; 11 | -------------------------------------------------------------------------------- /src/jena/tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jena-tests", 3 | "private": true, 4 | "description": "Jena Fuseki integration tests", 5 | "scripts": { 6 | "test": "jest --detectOpenHandles --verbose" 7 | }, 8 | "author": "SemApps Team", 9 | "license": "Apache-2.0", 10 | "devDependencies": { 11 | "jest": "^24.9.0", 12 | "supertest": "^4.0.2" 13 | }, 14 | "version": "0.2.0-alpha.0" 15 | } 16 | -------------------------------------------------------------------------------- /src/middleware/lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.1.3", 3 | "npmClient": "yarn", 4 | "useNx": true, 5 | "packages": ["packages/*", "tests"], 6 | "command": { 7 | "version": { 8 | "allowBranch": ["master", "next"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/middleware/nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasksRunnerOptions": { 3 | "default": { 4 | "runner": "nx/tasks-runners/default", 5 | "options": { 6 | "useDaemonProcess": false, 7 | "cacheableOperations": [] 8 | } 9 | } 10 | }, 11 | "affected": { 12 | "defaultBase": "master" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/middleware/packages/activitypub/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/activitypub 2 | 3 | ActivityPub module for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/activitypub) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/activitypub/containers.js: -------------------------------------------------------------------------------- 1 | const { FULL_ACTOR_TYPES, FULL_OBJECT_TYPES } = require('./constants'); 2 | 3 | module.exports = [ 4 | { 5 | path: '/as/actor', 6 | acceptedTypes: Object.values(FULL_ACTOR_TYPES) 7 | }, 8 | { 9 | path: '/as/object', 10 | acceptedTypes: Object.values(FULL_OBJECT_TYPES) 11 | } 12 | ]; 13 | -------------------------------------------------------------------------------- /src/middleware/packages/activitypub/index.js: -------------------------------------------------------------------------------- 1 | const constants = require('./constants'); 2 | 3 | module.exports = { 4 | ActivityPubService: require('./services/activitypub'), 5 | ActivityPubMigrationService: require('./services/migration'), 6 | ActivityMappingService: require('./services/activity-mapping'), 7 | RelayService: require('./services/relay'), 8 | // Mixins 9 | BotMixin: require('./mixins/bot'), 10 | ActivitiesHandlerMixin: require('./mixins/activities-handler'), 11 | // Misc. 12 | matchActivity: require('./utils/matchActivity'), 13 | containers: require('./containers'), 14 | ...constants 15 | }; 16 | -------------------------------------------------------------------------------- /src/middleware/packages/activitypub/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/activitypub", 3 | "version": "1.1.3", 4 | "description": "ActivityPub module for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@rdfjs/data-model": "^1.3.4", 9 | "@semapps/crypto": "1.1.3", 10 | "@semapps/ldp": "1.1.3", 11 | "@semapps/middlewares": "1.1.3", 12 | "@semapps/mime-types": "1.1.3", 13 | "@semapps/ontologies": "1.1.3", 14 | "@semapps/triplestore": "1.1.3", 15 | "handlebars": "^4.7.7", 16 | "moleculer": "^0.14.18", 17 | "moleculer-bull": "^0.2.5", 18 | "moleculer-db": "^0.8.16", 19 | "moleculer-web": "^0.10.0-beta1", 20 | "node-fetch": "^2.6.6", 21 | "sparqljs": "^3.5.2", 22 | "url-join": "^4.0.1" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "gitHead": "06cb2decdab424e8686a5d77cc3364fbf1912439", 28 | "engines": { 29 | "node": ">=14" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/middleware/packages/activitypub/utilTypes.d.ts: -------------------------------------------------------------------------------- 1 | export declare async function waitForResource( 2 | ms: number, 3 | fieldNames?: keyof T | string | (string | keyof T)[], 4 | maxTries: number, 5 | callback: () => T 6 | ): T; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/auth 2 | 3 | Authentication module for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/auth) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | AuthCASService: require('./services/auth.cas'), 3 | AuthLocalService: require('./services/auth.local'), 4 | AuthOIDCService: require('./services/auth.oidc'), 5 | AuthAccountService: require('./services/account'), 6 | AuthJWTService: require('./services/jwt'), 7 | AuthMigrationService: require('./services/migration'), 8 | AuthMailService: require('./services/mail') 9 | }; 10 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/middlewares/localLogout.js: -------------------------------------------------------------------------------- 1 | const localLogout = (req, res, next) => { 2 | req.logout(); // Passport logout 3 | next(); 4 | }; 5 | 6 | module.exports = localLogout; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/middlewares/redirectToFront.js: -------------------------------------------------------------------------------- 1 | const redirectToFront = (req, res) => { 2 | // Redirect browser to the redirect URL pushed in session 3 | const redirectUrl = new URL(req.session.redirectUrl); 4 | if (req.user) { 5 | // If a token was stored, add it to the URL so that the client may use it 6 | if (req.user.token) redirectUrl.searchParams.set('token', req.user.token); 7 | redirectUrl.searchParams.set('new', req.user.newUser ? 'true' : 'false'); 8 | } 9 | // Redirect using NodeJS HTTP 10 | res.writeHead(302, { Location: redirectUrl.toString() }); 11 | res.end(); 12 | }; 13 | 14 | module.exports = redirectToFront; 15 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/middlewares/saveRedirectUrl.js: -------------------------------------------------------------------------------- 1 | const saveRedirectUrl = (req, res, next) => { 2 | // Persist referer on the session to get it back after redirection 3 | // If the redirectUrl is already in the session, use it as default value 4 | req.session.redirectUrl = 5 | req.query.redirectUrl || (req.session && req.session.redirectUrl) || req.headers.referer || '/'; 6 | next(); 7 | }; 8 | 9 | module.exports = saveRedirectUrl; 10 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/middlewares/sendToken.js: -------------------------------------------------------------------------------- 1 | const sendToken = (req, res) => { 2 | res.setHeader('Content-Type', 'application/json'); 3 | res.end(JSON.stringify({ token: req.user.token, webId: req.user.webId, newUser: req.user.newUser })); 4 | }; 5 | 6 | module.exports = sendToken; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/auth", 3 | "version": "1.1.3", 4 | "description": "Authentification module for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/ldp": "1.1.3", 9 | "@semapps/middlewares": "1.1.3", 10 | "@semapps/mime-types": "1.1.3", 11 | "@semapps/triplestore": "1.1.3", 12 | "bcrypt": "^5.0.1", 13 | "express-session": "^1.17.0", 14 | "jsonwebtoken": "^9.0.2", 15 | "moleculer": "^0.14.17", 16 | "moleculer-db": "^0.8.16", 17 | "moleculer-mail": "^1.2.5", 18 | "moleculer-web": "^0.10.0-beta1", 19 | "openid-client": "^4.7.4", 20 | "passport": "^0.4.1", 21 | "passport-cas2": "0.0.12", 22 | "passport-local": "^1.0.0", 23 | "pug": "^3.0.2", 24 | "speakingurl": "^14.0.1", 25 | "url-join": "^4.0.1" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | }, 30 | "engines": { 31 | "node": ">=14" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/templates/reset-password/en-EN/subject.hbs: -------------------------------------------------------------------------------- 1 | Password reset for {{account.username}} account -------------------------------------------------------------------------------- /src/middleware/packages/auth/templates/reset-password/en-EN/text.hbs: -------------------------------------------------------------------------------- 1 | Hello {{account.username}}, 2 | 3 | In order to reset your password, please click on the link below: 4 | 5 | {{{resetUrl}}} 6 | 7 | If you did not request a password reset, please ignore this message. 8 | -------------------------------------------------------------------------------- /src/middleware/packages/auth/templates/reset-password/fr-FR/subject.hbs: -------------------------------------------------------------------------------- 1 | Réinitialisation du mot de passe du compte {{account.username}} -------------------------------------------------------------------------------- /src/middleware/packages/auth/templates/reset-password/fr-FR/text.hbs: -------------------------------------------------------------------------------- 1 | Bonjour {{account.username}}, 2 | 3 | Pour réinitialiser votre mot de passe, veuillez cliquer sur le lien ci-dessous: 4 | 5 | {{{resetUrl}}} 6 | 7 | Si vous n'avez pas fait une telle demande, vous pouvez ignorer ce message. 8 | -------------------------------------------------------------------------------- /src/middleware/packages/backup/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/backup 2 | 3 | Backup of datasets and uploaded files for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/backup) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/backup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/backup", 3 | "version": "1.1.3", 4 | "description": "Backup of datasets and uploaded files for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "cron": "^1.8.2", 9 | "fs-extra": "^10.0.0", 10 | "moleculer": "^0.14.31", 11 | "rsync": "^0.6.1", 12 | "ssh2-sftp-client": "^7.2.1" 13 | }, 14 | "publishConfig": { 15 | "access": "public" 16 | }, 17 | "engines": { 18 | "node": ">=14" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/middleware/packages/backup/utils/fsCopy.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const { join: pathJoin } = require('path'); 3 | 4 | const fsCopy = async (path, subDir, remoteServer) => { 5 | const destDir = pathJoin(remoteServer.path, subDir); 6 | await fs.copy(path, destDir); 7 | }; 8 | 9 | module.exports = fsCopy; 10 | -------------------------------------------------------------------------------- /src/middleware/packages/backup/utils/fsRemove.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join: pathJoin } = require('path'); 3 | 4 | const fsRemove = async (removeFiles, subDir, remoteServer) => { 5 | await Promise.all( 6 | removeFiles 7 | .map(file => pathJoin(remoteServer.path, subDir, file)) 8 | .map(file => fs.promises.rm(file, { force: true })) 9 | ); 10 | }; 11 | 12 | module.exports = fsRemove; 13 | -------------------------------------------------------------------------------- /src/middleware/packages/backup/utils/ftpRemove.js: -------------------------------------------------------------------------------- 1 | const Client = require('ssh2-sftp-client'); 2 | const { join: pathJoin } = require('path'); 3 | 4 | const ftpRemove = (removeFiles, remoteServer) => { 5 | return new Promise((resolve, reject) => { 6 | const sftp = new Client(); 7 | sftp 8 | .connect({ 9 | host: remoteServer.host, 10 | port: remoteServer.port, 11 | username: remoteServer.user, 12 | password: remoteServer.password 13 | }) 14 | .then(async () => { 15 | for (const filename of removeFiles) { 16 | await sftp.delete(pathJoin(remoteServer.path, filename), true); 17 | } 18 | resolve(); 19 | }) 20 | .catch(e => reject(e)); 21 | }); 22 | }; 23 | 24 | module.exports = ftpRemove; 25 | -------------------------------------------------------------------------------- /src/middleware/packages/backup/utils/rsyncCopy.js: -------------------------------------------------------------------------------- 1 | const Rsync = require('rsync'); 2 | const { join: pathJoin } = require('path'); 3 | 4 | const rsyncCopy = (path, subDir, remoteServer, syncDelete = false) => { 5 | // Setup rsync to remote server 6 | const rsync = new Rsync() 7 | .flags('arv') 8 | .set('e', `sshpass -p "${remoteServer.password}" ssh -o StrictHostKeyChecking=no`) 9 | .source(path) 10 | .destination(`${remoteServer.user}@${remoteServer.host}:${pathJoin(remoteServer.path, subDir)}`); 11 | 12 | if (syncDelete) rsync.set('delete'); 13 | 14 | return new Promise((resolve, reject) => { 15 | console.log(`Rsync started with command: ${rsync.command()}`); 16 | rsync.execute(error => { 17 | if (error) { 18 | reject(error); 19 | } else { 20 | console.log('Rsync finished !'); 21 | resolve(); 22 | } 23 | }); 24 | }); 25 | }; 26 | 27 | module.exports = rsyncCopy; 28 | -------------------------------------------------------------------------------- /src/middleware/packages/core/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/core 2 | 3 | Core SemApps services 4 | 5 | [Documentation](https://semapps.org/docs/middleware/core) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/core/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | CoreService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/core", 3 | "version": "1.1.3", 4 | "description": "SemApps core services", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/activitypub": "1.1.3", 9 | "@semapps/crypto": "1.1.3", 10 | "@semapps/jsonld": "1.1.3", 11 | "@semapps/ldp": "1.1.3", 12 | "@semapps/ontologies": "1.1.3", 13 | "@semapps/sparql-endpoint": "1.1.3", 14 | "@semapps/triplestore": "1.1.3", 15 | "@semapps/void": "1.1.3", 16 | "@semapps/webacl": "1.1.3", 17 | "@semapps/webfinger": "1.1.3", 18 | "@semapps/webid": "1.1.3", 19 | "moleculer": "^0.14.19", 20 | "moleculer-web": "^0.10.0-beta1", 21 | "url-join": "^4.0.1" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | }, 26 | "engines": { 27 | "node": ">=14" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/middleware/packages/core/serviceTypes.d.ts: -------------------------------------------------------------------------------- 1 | import { Context, ServiceSettingSchema } from 'moleculer'; 2 | 3 | export interface CoreServiceSettings extends ServiceSettingSchema { 4 | baseUrl?: string; 5 | baseDir?: string; 6 | triplestore: { 7 | url?: string; 8 | user?: string; 9 | password?: string; 10 | mainDataset?: string; 11 | }; 12 | // Optional 13 | containers?: string; 14 | ontologies?: string; 15 | // Services configurations, no typings yet. 16 | activitypub: object; 17 | api: object; 18 | jsonld: object; 19 | ldp: object; 20 | signature: object; 21 | sparqlEndpoint: object; 22 | void: object; 23 | webacl: object; 24 | webfinger: object; 25 | } 26 | 27 | export interface MethodAuthenticateContext extends Context {} 28 | -------------------------------------------------------------------------------- /src/middleware/packages/crypto/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('./keys'), 3 | ...require('./signature'), 4 | ...require('./constants'), 5 | ...require('./verifiable-credentials') 6 | }; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/crypto/keys/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | MigrationService: require('./migration'), 3 | KeysService: require('./keys') 4 | }; 5 | -------------------------------------------------------------------------------- /src/middleware/packages/crypto/signature/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SignatureService: require('./http-signatures'), 3 | ProxyService: require('./proxy'), 4 | KeyPairService: require('./keypair') 5 | }; 6 | -------------------------------------------------------------------------------- /src/middleware/packages/crypto/verifiable-credentials/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | DataIntegrityService: require('./data-integrity-service'), 3 | VerifiableCredentialsService: require('./vc-service'), 4 | VCPurpose: require('./VcPurpose'), 5 | VCCapabilityPresentationProofPurpose: require('./VcCapabilityPresentationProofPurpose') 6 | }; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/importer/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/importer 2 | 3 | JSON importer and synchronizer for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/importer/index) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/importer/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ImporterMixin: require('./mixins/importer'), 3 | DiscourseImporterMixin: require('./mixins/discourse'), 4 | DrupalImporterMixin: require('./mixins/drupal'), 5 | GoGoCartoImporterMixin: require('./mixins/gogocarto'), 6 | HumHubImporterMixin: require('./mixins/humhub'), 7 | JotformImporterMixin: require('./mixins/jotform'), 8 | MobilizonImporterMixin: require('./mixins/mobilizon'), 9 | PrestaShopImporterMixin: require('./mixins/prestashop'), 10 | YesWikiImporterMixin: require('./mixins/yeswiki'), 11 | WordpressImporterMixin: require('./mixins/wordpress'), 12 | ...require('./utils') 13 | }; 14 | -------------------------------------------------------------------------------- /src/middleware/packages/importer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/importer", 3 | "version": "1.1.3", 4 | "description": "JSON importer and synchronizer for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/activitypub": "1.1.3", 9 | "@semapps/ldp": "1.1.3", 10 | "@semapps/mime-types": "1.1.3", 11 | "cron-parser": "^4.2.1", 12 | "google-libphonenumber": "^3.2.26", 13 | "node-fetch": "^2.6.6", 14 | "sanitize-html": "^2.6.1", 15 | "url-join": "^4.0.1" 16 | }, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "gitHead": "06cb2decdab424e8686a5d77cc3364fbf1912439", 21 | "engines": { 22 | "node": ">=14" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/middleware/packages/inference/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/inference 2 | 3 | Inference engine for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/inference) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/inference/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | InferenceService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/inference/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/inference", 3 | "version": "1.1.3", 4 | "description": "Inference engine for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/activitypub": "1.1.3", 9 | "n3": "^1.6.3", 10 | "node-fetch": "^2.6.6", 11 | "url-join": "^4.0.1" 12 | }, 13 | "publishConfig": { 14 | "access": "public" 15 | }, 16 | "engines": { 17 | "node": ">=14" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/jsonld 2 | 3 | JsonLD utilities for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/jsonld) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | JsonLdService: require('./service'), 3 | JsonLdApiService: require('./services/api'), 4 | JsonLdContextService: require('./services/context'), 5 | JsonLdDocumentLoaderService: require('./services/document-loader'), 6 | JsonLdParserService: require('./services/parser'), 7 | uriSchemes: require('./utils/uriSchemes'), 8 | isRegisteredURI: require('./utils/utils').isRegisteredURI 9 | }; 10 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/jsonld", 3 | "version": "1.1.3", 4 | "description": "JsonLD utils for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "jsonld": "^3.3.2", 9 | "jsonld-context-parser": "^2.4.0", 10 | "jsonld-streaming-parser": "^2.4.2", 11 | "lru-cache": "^6.0.0", 12 | "streamify-string": "^1.0.1", 13 | "url-join": "^4.0.1" 14 | }, 15 | "devDependencies": { 16 | "@types/jsonld": "1.5.15" 17 | }, 18 | "publishConfig": { 19 | "access": "public" 20 | }, 21 | "engines": { 22 | "node": ">=14" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/services/api/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'jsonld.api', 3 | settings: { 4 | localContextPath: null 5 | }, 6 | dependencies: ['api'], 7 | async started() { 8 | await this.broker.call('api.addRoute', { 9 | route: { 10 | path: this.settings.localContextPath, 11 | name: `local-jsonld-context`, 12 | bodyParsers: { 13 | json: true 14 | }, 15 | aliases: { 16 | 'GET /': 'jsonld.api.getContext' 17 | } 18 | } 19 | }); 20 | }, 21 | actions: { 22 | async getContext(ctx) { 23 | ctx.meta.$responseType = 'application/ld+json'; 24 | return await ctx.call('jsonld.context.getLocal'); 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/services/context/actions/get.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | cache: true, 4 | async handler(ctx) { 5 | let context = []; 6 | 7 | const ontologies = await ctx.call('ontologies.list'); 8 | 9 | for (const ontology of ontologies) { 10 | if (ontology.preserveContextUri === true) { 11 | // If we want to parse, we don't need a special merge operation 12 | context = context.concat(ontology.jsonldContext); 13 | } 14 | } 15 | 16 | const localContext = await this.actions.getLocal({}, { parentCtx: ctx }); 17 | // Include the local context only if it is not empty 18 | if (Object.keys(localContext['@context']).length > 0) { 19 | context = context.concat(this.settings.localContextUri); 20 | } 21 | 22 | return context; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/services/context/actions/getLocal.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | cache: true, 4 | async handler(ctx) { 5 | let context = []; 6 | 7 | let ontologies = await ctx.call('ontologies.list'); 8 | 9 | // Do not include ontologies which want to preserve their context URI 10 | ontologies = ontologies.filter(ont => ont.preserveContextUri !== true); 11 | 12 | for (const ontology of ontologies) { 13 | if (ontology.jsonldContext) { 14 | context = [].concat(ontology.jsonldContext, context); 15 | } 16 | } 17 | 18 | const prefixes = Object.fromEntries(ontologies.map(ont => [ont.prefix, ont.namespace])); 19 | 20 | context = await ctx.call('jsonld.context.parse', { 21 | context: [...context, prefixes] 22 | }); 23 | 24 | return { 25 | '@context': context 26 | }; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/services/context/actions/parse.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | params: { 4 | context: { 5 | type: 'multi', 6 | rules: [{ type: 'array' }, { type: 'object' }, { type: 'string' }] 7 | }, 8 | options: { type: 'object', optional: true } 9 | }, 10 | async handler(ctx) { 11 | const { context, options } = ctx.params; 12 | const { contextRaw } = await this.contextParser.parse(context, options); 13 | return contextRaw; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/middleware/packages/jsonld/services/context/actions/validate.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | params: { 4 | context: { 5 | type: 'multi', 6 | rules: [{ type: 'array' }, { type: 'object' }, { type: 'string' }] 7 | } 8 | }, 9 | async handler(ctx) { 10 | const { context } = ctx.params; 11 | try { 12 | await this.contextParser.parse(context); 13 | return true; 14 | } catch (e) { 15 | this.logger.warn(`Could not parse context. Error: ${e.message}`); 16 | return false; 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/ldp 2 | 3 | LDP module for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/ldp/index) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/api/actions/delete.js: -------------------------------------------------------------------------------- 1 | module.exports = async function patch(ctx) { 2 | try { 3 | const { username, slugParts } = ctx.params; 4 | 5 | const uri = this.getUriFromSlugParts(slugParts, username); 6 | const types = await ctx.call('ldp.resource.getTypes', { resourceUri: uri }); 7 | 8 | if (types.includes('http://www.w3.org/ns/ldp#Container')) { 9 | await ctx.call('ldp.container.delete', { containerUri: uri }); 10 | } else { 11 | const { controlledActions } = await ctx.call('ldp.registry.getByUri', { resourceUri: uri }); 12 | await ctx.call(controlledActions.delete || 'ldp.resource.delete', { resourceUri: uri }); 13 | } 14 | 15 | ctx.meta.$statusCode = 204; 16 | ctx.meta.$responseHeaders = { 17 | Link: '; rel="type"', 18 | 'Content-Length': 0 19 | }; 20 | } catch (e) { 21 | if (e.code !== 404 && e.code !== 403) console.error(e); 22 | ctx.meta.$statusCode = e.code || 500; 23 | ctx.meta.$statusMessage = e.message; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/api/actions/head.js: -------------------------------------------------------------------------------- 1 | module.exports = async function head(ctx) { 2 | try { 3 | const { username, slugParts } = ctx.params; 4 | const uri = this.getUriFromSlugParts(slugParts, username); 5 | 6 | const linkHeader = await ctx.call('ldp.link-header.get', { uri }); 7 | 8 | ctx.meta.$statusCode = 200; 9 | ctx.meta.$statusMessage = 'OK'; 10 | ctx.meta.$responseHeaders = { 11 | Link: linkHeader, 12 | 'Content-Length': 0 13 | }; 14 | } catch (e) { 15 | if (e.code !== 404 && e.code !== 403) console.error(e); 16 | ctx.meta.$statusCode = e.code || 500; 17 | ctx.meta.$statusMessage = e.message; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/container/actions/clear.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | params: { 4 | containerUri: { type: 'string' }, 5 | webId: { type: 'string', optional: true } 6 | }, 7 | async handler(ctx) { 8 | let { containerUri, webId } = ctx.params; 9 | 10 | const resourcesUris = await this.actions.getUris({ containerUri }, { parentCtx: ctx }); 11 | 12 | this.logger.info(`Deleting ${resourcesUris.length} resources...`); 13 | 14 | for (let resourceUri of resourcesUris) { 15 | this.logger.info(`Deleting ${resourceUri}...`); 16 | await ctx.call('ldp.resource.delete', { resourceUri, webId }); 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/container/actions/getAll.js: -------------------------------------------------------------------------------- 1 | const { MIME_TYPES } = require('@semapps/mime-types'); 2 | 3 | module.exports = { 4 | visibility: 'public', 5 | params: { 6 | dataset: { type: 'string', optional: true } 7 | }, 8 | async handler(ctx) { 9 | const result = await ctx.call('triplestore.query', { 10 | query: ` 11 | PREFIX ldp: 12 | SELECT ?containerUri 13 | WHERE { 14 | ?containerUri a ldp:Container . 15 | } 16 | `, 17 | accept: MIME_TYPES.JSON, 18 | dataset: ctx.params.dataset, 19 | webId: 'system' 20 | }); 21 | 22 | return result.map(node => node.containerUri.value); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/container/actions/getUris.js: -------------------------------------------------------------------------------- 1 | const { MIME_TYPES } = require('@semapps/mime-types'); 2 | 3 | module.exports = { 4 | visibility: 'public', 5 | params: { 6 | containerUri: { type: 'string', optional: true } 7 | }, 8 | async handler(ctx) { 9 | const { containerUri } = ctx.params; 10 | 11 | const result = await ctx.call('triplestore.query', { 12 | query: ` 13 | PREFIX ldp: 14 | SELECT ?resourceUri 15 | WHERE { 16 | <${containerUri}> ldp:contains ?resourceUri . 17 | } 18 | `, 19 | accept: MIME_TYPES.JSON, 20 | webId: 'system' 21 | }); 22 | 23 | return result.map(node => node.resourceUri.value); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/container/actions/isEmpty.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | params: { 4 | containerUri: { type: 'string' }, 5 | webId: { 6 | type: 'string', 7 | optional: true 8 | } 9 | }, 10 | async handler(ctx) { 11 | const { containerUri } = ctx.params; 12 | const webId = ctx.params.webId || ctx.meta.webId || 'anon'; 13 | const { dataset } = ctx.meta; 14 | 15 | const res = await ctx.call('triplestore.query', { 16 | query: `SELECT (COUNT (?o) as ?count) { <${containerUri}> ?o }`, 17 | webId, 18 | dataset 19 | }); 20 | 21 | const num = Number(res[0].count.value); 22 | return num === 0; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/link-header/actions/register.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | params: { 4 | actionName: { type: 'string' } 5 | }, 6 | handler(ctx) { 7 | const { actionName } = ctx.params; 8 | this.registeredActionNames.push(actionName); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/link-header/index.js: -------------------------------------------------------------------------------- 1 | const getAction = require('./actions/get'); 2 | const registerAction = require('./actions/register'); 3 | 4 | module.exports = { 5 | name: 'ldp.link-header', 6 | actions: { 7 | get: getAction, 8 | register: registerAction 9 | }, 10 | async started() { 11 | this.registeredActionNames = []; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/registry/actions/getByType.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Find the container options for a resource type 3 | * This only returns containers registered with the LDP registry, not the ones registered with the TypeIndex. 4 | */ 5 | module.exports = { 6 | visibility: 'public', 7 | params: { 8 | type: { type: 'multi', rules: [{ type: 'string' }, { type: 'array' }] } 9 | }, 10 | async handler(ctx) { 11 | const { type } = ctx.params; 12 | const types = await ctx.call('jsonld.parser.expandTypes', { types: type }); 13 | const registeredContainers = await this.actions.list({}, { parentCtx: ctx }); 14 | 15 | return Object.values(registeredContainers).find(container => 16 | types.some(t => 17 | Array.isArray(container.acceptedTypes) ? container.acceptedTypes.includes(t) : container.acceptedTypes === t 18 | ) 19 | ); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/registry/actions/getUri.js: -------------------------------------------------------------------------------- 1 | const urlJoin = require('url-join'); 2 | 3 | /** 4 | * Get the container URI based on its path 5 | * In Pod provider config, the webId is required to find the Pod root 6 | */ 7 | module.exports = { 8 | visibility: 'public', 9 | params: { 10 | path: { type: 'string' }, 11 | webId: { type: 'string', optional: true } 12 | }, 13 | async handler(ctx) { 14 | const { path, webId } = ctx.params; 15 | 16 | if (this.settings.podProvider) { 17 | if (webId === 'system' || webId === 'anon') 18 | throw new Error(`You must provide a real webId param in Pod provider config. Received: ${webId}`); 19 | const podUrl = await ctx.call('solid-storage.getUrl', { webId }); 20 | return urlJoin(podUrl, path); 21 | } else { 22 | return urlJoin(this.settings.baseUrl, path); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/registry/actions/list.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | handler() { 4 | return this.registeredContainers; 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/remote/actions/getGraph.js: -------------------------------------------------------------------------------- 1 | const { triple, namedNode, variable } = require('@rdfjs/data-model'); 2 | 3 | module.exports = { 4 | visibility: 'public', 5 | params: { 6 | resourceUri: { type: 'string' } 7 | }, 8 | async handler(ctx) { 9 | const { resourceUri } = ctx.params; 10 | 11 | let exist = await ctx.call('triplestore.tripleExist', { 12 | triple: triple(namedNode(resourceUri), variable('p'), variable('s')), 13 | webId: 'system' 14 | }); 15 | 16 | if (exist) { 17 | return undefined; // Default graph 18 | } 19 | exist = await ctx.call('triplestore.tripleExist', { 20 | triple: triple(namedNode(resourceUri), variable('p'), variable('s')), 21 | graphName: this.settings.mirrorGraphName 22 | }); 23 | 24 | if (exist) { 25 | return this.settings.mirrorGraphName; 26 | } 27 | return false; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/services/resource/actions/getTypes.js: -------------------------------------------------------------------------------- 1 | const { MIME_TYPES } = require('@semapps/mime-types'); 2 | 3 | module.exports = { 4 | visibility: 'public', 5 | params: { 6 | resourceUri: 'string' 7 | }, 8 | cache: { 9 | keys: ['resourceUri'] 10 | }, 11 | async handler(ctx) { 12 | const { resourceUri } = ctx.params; 13 | 14 | const result = await ctx.call('triplestore.query', { 15 | query: ` 16 | SELECT ?type 17 | WHERE { 18 | <${resourceUri}> a ?type . 19 | } 20 | `, 21 | accept: MIME_TYPES.JSON, 22 | webId: 'system' 23 | }); 24 | 25 | return result.map(node => node.type.value); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/middleware/packages/ldp/utilTypes.d.ts: -------------------------------------------------------------------------------- 1 | export declare async function waitForResource( 2 | ms: number, 3 | fieldNames?: keyof T | string | (string | keyof T)[], 4 | maxTries: number, 5 | callback: () => T 6 | ): T; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/middlewares/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/middlewares 2 | 3 | Express Middlewares for SemApps 4 | -------------------------------------------------------------------------------- /src/middleware/packages/middlewares/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/middlewares", 3 | "version": "1.1.3", 4 | "description": "Express Middlewares for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/mime-types": "1.1.3", 9 | "busboy": "^0.3.1", 10 | "memory-streams": "^0.1.3", 11 | "moleculer": "^0.14.18" 12 | }, 13 | "publishConfig": { 14 | "access": "public" 15 | }, 16 | "engines": { 17 | "node": ">=14" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/middleware/packages/migration/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/migration 2 | 3 | SemApps migration utilities 4 | 5 | [Documentation](https://semapps.org/docs/middleware/migration) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/migration/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | MigrationService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/migration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/migration", 3 | "version": "1.1.3", 4 | "description": "SemApps migration utilities", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/ldp": "1.1.3", 9 | "@semapps/webacl": "1.1.3" 10 | }, 11 | "publishConfig": { 12 | "access": "public" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/middleware/packages/mime-types/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/mime-types 2 | 3 | MIME types handling for SemApps 4 | -------------------------------------------------------------------------------- /src/middleware/packages/mime-types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/mime-types", 3 | "version": "1.1.3", 4 | "description": "MIME types handling for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "moleculer": "^0.14.18", 9 | "negotiator": "^0.6.2" 10 | }, 11 | "publishConfig": { 12 | "access": "public" 13 | }, 14 | "gitHead": "06cb2decdab424e8686a5d77cc3364fbf1912439", 15 | "engines": { 16 | "node": ">=14" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/middleware/packages/nodeinfo/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NodeinfoService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/nodeinfo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/nodeinfo", 3 | "version": "1.1.3", 4 | "description": "Nodeinfo extension for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "url-join": "^4.0.1" 9 | }, 10 | "publishConfig": { 11 | "access": "public" 12 | }, 13 | "engines": { 14 | "node": ">=14" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/middleware/packages/notifications/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/notifications 2 | 3 | Notifications tools for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/notifications) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/notifications/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | DigestNotificationsService: require('./services/digest/service'), 3 | ExpoPushNotificationsService: require('./services/expo-push/service'), 4 | SingleMailNotificationsService: require('./services/single-mail/service') 5 | }; 6 | -------------------------------------------------------------------------------- /src/middleware/packages/notifications/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/notifications", 3 | "version": "1.1.3", 4 | "description": "Notifications tools for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/ldp": "1.1.3", 9 | "@semapps/triplestore": "1.1.3", 10 | "cron-parser": "^4.3.0", 11 | "expo-server-sdk": "^3.4.0", 12 | "moleculer": "^0.14.18", 13 | "moleculer-db": "^0.8.15", 14 | "moleculer-mail": "^1.2.5", 15 | "url-join": "^4.0.1" 16 | }, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "engines": { 21 | "node": ">=14" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/middleware/packages/notifications/services/digest/subscription.js: -------------------------------------------------------------------------------- 1 | const DbService = require('moleculer-db'); 2 | const { TripleStoreAdapter } = require('@semapps/triplestore'); 3 | 4 | module.exports = { 5 | name: 'digest.subscription', 6 | mixins: [DbService], 7 | adapter: new TripleStoreAdapter({ type: 'DigestSubscription', dataset: 'settings' }), 8 | settings: { 9 | idField: '@id' 10 | }, 11 | dependencies: ['triplestore'], 12 | actions: { 13 | async findByWebId(ctx) { 14 | const { webId } = ctx.params; 15 | const subscriptions = await this._find(ctx, { query: { webId } }); 16 | return subscriptions.length > 0 ? subscriptions[0] : null; 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/middleware/packages/notifications/templates/single-mail/subject.hbs: -------------------------------------------------------------------------------- 1 | {{{title}}} -------------------------------------------------------------------------------- /src/middleware/packages/notifications/templates/single-mail/text.hbs: -------------------------------------------------------------------------------- 1 | {{title}} : 2 | 3 | {{description}} 4 | 5 | {{actionName}}: 6 | {{actionLink}} -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/ontologies 2 | 3 | SemApps ontologies 4 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/actions/findNamespace.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | 3 | module.exports = { 4 | visibility: 'public', 5 | params: { 6 | prefix: 'string' 7 | }, 8 | async handler(ctx) { 9 | const { prefix } = ctx.params; 10 | 11 | const response = await fetch(`http://prefix.cc/${prefix}.file.json`); 12 | 13 | if (response.ok) { 14 | const json = await response.json(); 15 | 16 | return json && json[prefix]; 17 | } 18 | 19 | return null; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/actions/findPrefix.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { isURL } = require('../utils'); 3 | 4 | module.exports = { 5 | visibility: 'public', 6 | params: { 7 | uri: 'string' 8 | }, 9 | async handler(ctx) { 10 | const { uri } = ctx.params; 11 | 12 | if (!isURL(uri)) throw new Error(`The uri param of the ontologies.findPrefix action must be a full URL`); 13 | 14 | const response = await fetch(`http://prefix.cc/?q=${encodeURIComponent(uri)}`, { redirect: 'manual' }); 15 | 16 | if (response.status === 302) { 17 | const redirectUrl = response.headers.get('Location'); 18 | 19 | const result = redirectUrl?.replace('http://prefix.cc/', '').split(':'); 20 | 21 | return result && result[0]; 22 | } 23 | 24 | return null; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/actions/getPrefixes.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | cache: true, 4 | async handler(ctx) { 5 | const ontologies = await this.actions.list({}, { parentCtx: ctx }); 6 | return Object.fromEntries( 7 | ontologies 8 | .sort((a, b) => (a.prefix < b.prefix ? -1 : a.prefix > b.prefix ? 1 : 0)) 9 | .map(ontology => [ontology.prefix, ontology.namespace]) 10 | ); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/actions/getRdfPrefixes.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | cache: true, 4 | async handler(ctx) { 5 | const ontologies = await this.actions.list({}, { parentCtx: ctx }); 6 | return ontologies 7 | .sort((a, b) => (a.prefix < b.prefix ? -1 : a.prefix > b.prefix ? 1 : 0)) 8 | .map(ontology => `PREFIX ${ontology.prefix}: <${ontology.namespace}>`) 9 | .join('\n'); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/actions/list.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | visibility: 'public', 3 | cache: true, 4 | handler() { 5 | return Object.values(this.ontologies); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/actions/prefixToUri.js: -------------------------------------------------------------------------------- 1 | const { isURL } = require('../utils'); 2 | 3 | const regexPrefix = /^([^:]+):([^:]+)$/gm; 4 | 5 | module.exports = { 6 | visibility: 'public', 7 | params: { 8 | value: 'string' 9 | }, 10 | cache: true, 11 | async handler(ctx) { 12 | const { value } = ctx.params; 13 | 14 | // Check if this is already a full URI 15 | if (isURL(value)) return value; 16 | 17 | if (!value.match(regexPrefix)) throw new Error(`The provided value ${value} is neither prefixed, nor a full URI`); 18 | 19 | const matchResults = regexPrefix.exec(value); 20 | const prefix = matchResults[1]; 21 | 22 | const ontology = await this.actions.get({ prefix }); 23 | if (!ontology) throw new Error(`No ontology found with prefix ${prefix}`); 24 | 25 | return value.replace(`${ontology.prefix}:`, ontology.namespace); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/index.js: -------------------------------------------------------------------------------- 1 | const OntologiesService = require('./service'); 2 | const OntologiesRegistryService = require('./sub-services/registry'); 3 | const coreOntologies = require('./ontologies/core'); 4 | const customOntologies = require('./ontologies/custom'); 5 | const solidOntologies = require('./ontologies/solid'); 6 | 7 | module.exports = { 8 | OntologiesService, 9 | OntologiesRegistryService, 10 | coreOntologies: Object.values(coreOntologies), 11 | solidOntologies: Object.values(solidOntologies), 12 | customOntologies: Object.values(customOntologies), 13 | ...coreOntologies, 14 | ...solidOntologies, 15 | ...customOntologies 16 | }; 17 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/acl.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "acl", 3 | "namespace": "http://www.w3.org/ns/auth/acl#", 4 | "jsonldContext": { 5 | "xsd": "http://www.w3.org/2001/XMLSchema#", 6 | "acl:accessTo": { 7 | "@type": "@id" 8 | }, 9 | "acl:agent": { 10 | "@type": "@id" 11 | }, 12 | "acl:agentGroup": { 13 | "@type": "@id" 14 | }, 15 | "acl:agentClass": { 16 | "@type": "@id" 17 | }, 18 | "acl:default": { 19 | "@type": "@id" 20 | }, 21 | "acl:mode": { 22 | "@type": "@id" 23 | }, 24 | "acl:Authorization": { 25 | "@type": "@id" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/as.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "as", 3 | "namespace": "https://www.w3.org/ns/activitystreams#", 4 | "jsonldContext": "https://www.w3.org/ns/activitystreams", 5 | "preserveContextUri": true 6 | } 7 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/cred.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "cred", 3 | "namespace": "https://www.w3.org/2018/credentials#", 4 | "preserveContextUri": false, 5 | "jsonldContext": { 6 | "credentialSubject": { 7 | "@id": "https://www.w3.org/2018/credentials#credentialSubject", 8 | "@type": "@id" 9 | }, 10 | "holder": { 11 | "@id": "https://www.w3.org/2018/credentials#holder", 12 | "@type": "@id" 13 | }, 14 | "issuer": { 15 | "@id": "https://www.w3.org/2018/credentials#issuer", 16 | "@type": "@id" 17 | }, 18 | "verifiableCredential": "https://www.w3.org/2018/credentials#verifiableCredential", 19 | "VerifiableCredential": "https://www.w3.org/2018/credentials#VerifiableCredential", 20 | "VerifiablePresentation": "https://www.w3.org/2018/credentials#VerifiablePresentation" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/dc.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "dc", 3 | "namespace": "http://purl.org/dc/terms/", 4 | "jsonldContext": { 5 | "xsd": "http://www.w3.org/2001/XMLSchema#", 6 | "dc:created": { 7 | "@type": "xsd:dateTime" 8 | }, 9 | "dc:modified": { 10 | "@type": "xsd:dateTime" 11 | }, 12 | "dc:creator": { 13 | "@type": "@id" 14 | }, 15 | "dc:source": { 16 | "@type": "@id" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/did.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "did", 3 | "namespace": "https://www.w3.org/ns/did#", 4 | "jsonldContext": { 5 | "service": { 6 | "@id": "https://www.w3.org/ns/did#service", 7 | "@type": "@id", 8 | "@context": { 9 | "@protected": true, 10 | "id": "@id", 11 | "type": "@type", 12 | "serviceEndpoint": { 13 | "@id": "https://www.w3.org/ns/did#serviceEndpoint", 14 | "@type": "@id" 15 | } 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/foaf.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "foaf", 3 | "namespace": "http://xmlns.com/foaf/0.1/" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | acl: require('./acl.json'), 3 | as: require('./as.json'), 4 | cred: require('./cred.json'), 5 | dc: require('./dc.json'), 6 | did: require('./did.json'), 7 | foaf: require('./foaf.json'), 8 | ldp: require('./ldp.json'), 9 | rdf: require('./rdf.json'), 10 | rdfs: require('./rdfs.json'), 11 | sec: require('./sec.json'), 12 | semapps: require('./semapps.json'), 13 | skos: require('./skos.json'), 14 | vcard: require('./vcard.json'), 15 | void: require('./void.json'), 16 | xsd: require('./xsd.json') 17 | }; 18 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/ldp.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "ldp", 3 | "namespace": "http://www.w3.org/ns/ldp#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/rdf.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "rdf", 3 | "namespace": "http://www.w3.org/1999/02/22-rdf-syntax-ns#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/rdfs.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "rdfs", 3 | "namespace": "http://www.w3.org/2000/01/rdf-schema#", 4 | "jsonldContext": { 5 | "rdfs:seeAlso": { "@type": "@id" } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/semapps.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "semapps", 3 | "namespace": "http://semapps.org/ns/core#", 4 | "jsonldContext": { 5 | "semapps:sortPredicate": { 6 | "@type": "@id" 7 | }, 8 | "semapps:sortOrder": { 9 | "@type": "@id" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/skos.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "skos", 3 | "namespace": "http://www.w3.org/2008/05/skos#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/vcard.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "vcard", 3 | "namespace": "http://www.w3.org/2006/vcard/ns#", 4 | "jsonldContext": { 5 | "vcard:hasAddress": { 6 | "@type": "@id" 7 | }, 8 | "vcard:hasGeo": { 9 | "@type": "@id" 10 | }, 11 | "vcard:photo": { 12 | "@type": "@id" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/void.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "void", 3 | "namespace": "http://rdfs.org/ns/void#", 4 | "jsonldContext": { 5 | "xsd": "http://www.w3.org/2001/XMLSchema#", 6 | "void:feature": { 7 | "@type": "@id" 8 | }, 9 | "void:sparqlEndpoint": { 10 | "@type": "@id" 11 | }, 12 | "void:rootResource": { 13 | "@type": "@id" 14 | }, 15 | "void:vocabulary": { 16 | "@type": "@id" 17 | }, 18 | "void:entities": { "@type": "xsd:integer" }, 19 | "void:doNotMirror": { "@type": "xsd:boolean" }, 20 | "void:class": { "@type": "@id" }, 21 | "void:classPartition": { "@type": "@id" } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/core/xsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "xsd", 3 | "namespace": "http://www.w3.org/2001/XMLSchema#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | mp: require('./mp.json'), 3 | oasis: require('./oasis.json'), 4 | og: require('./og.json'), 5 | pair: require('./pair.json'), 6 | petr: require('./petr.json'), 7 | schema: require('./schema.json'), 8 | skos: require('./skos.json'), 9 | syreen: require('./syreen.json'), 10 | tutor: require('./tutor.json') 11 | }; 12 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/mp.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "mp", 3 | "namespace": "http://virtual-assembly.org/ontologies/pair-mp#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/oasis.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "oasis", 3 | "namespace": "http://cooperative-oasis.org/ns/core#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/og.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "og", 3 | "namespace": "http://virtual-assembly.org/ontologies/organigraph#", 4 | "owl": "https://raw.githubusercontent.com/assemblee-virtuelle/organigraph/master/ontology/organigraph.owl", 5 | "jsonldContext": { 6 | "og:leads": { 7 | "@type": "@id" 8 | }, 9 | "og:leadBy": { 10 | "@type": "@id" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/petr.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "petr", 3 | "namespace": "https://data.petr-msb.data-players.com/ontology#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "schema", 3 | "namespace": "http://schema.org/" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/skos.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "skos", 3 | "namespace": "http://www.w3.org/2004/02/skos/core#", 4 | "owl": "https://raw.githubusercontent.com/openlink/rdf-editor/develop/app/data/skos.ttl", 5 | "jsonldContext": { 6 | "skos:broader": { 7 | "@type": "@id" 8 | }, 9 | "skos:narrower": { 10 | "@type": "@id" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/syreen.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "syreen", 3 | "namespace": "http://syreen.fr/ns/core#", 4 | "jsonldContext": { 5 | "xsd": "http://www.w3.org/2001/XMLSchema#", 6 | "syreen:hasPart": { 7 | "@type": "@id" 8 | }, 9 | "syreen:actor": { 10 | "@type": "@id" 11 | }, 12 | "syreen:partOf": { 13 | "@type": "@id" 14 | }, 15 | "syreen:depictedBy": { 16 | "@type": "@id" 17 | }, 18 | "syreen:hasLocation": { 19 | "@type": "@id" 20 | }, 21 | "syreen:hasCategory": { 22 | "@type": "@id" 23 | }, 24 | "syreen:hasBatiprixCategory": { 25 | "@type": "@id" 26 | }, 27 | "syreen:hasUnit": { 28 | "@type": "@id" 29 | }, 30 | "syreen:hasStage": { 31 | "@type": "@id" 32 | }, 33 | "syreen:hasProjectType": { 34 | "@type": "@id" 35 | }, 36 | "syreen:startDate": { 37 | "@type": "xsd:dateTime" 38 | }, 39 | "syreen:endDate": { 40 | "@type": "xsd:dateTime" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/custom/tutor.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "tutor", 3 | "namespace": "http://virtual-assembly.org/ontologies/pair-tutor#", 4 | "owl": "https://raw.githubusercontent.com/reconnexion/minicourses/master/ontology/pair-tutor.owl", 5 | "jsonldContext": { 6 | "xsd": "http://www.w3.org/2001/XMLSchema#", 7 | "tutor:currentLesson": { 8 | "@type": "@id" 9 | }, 10 | "tutor:hasRegistration": { 11 | "@type": "@id" 12 | }, 13 | "tutor:registeredFor": { 14 | "@type": "@id" 15 | }, 16 | "tutor:registrant": { 17 | "@type": "@id" 18 | }, 19 | "tutor:registrationFor": { 20 | "@type": "@id" 21 | }, 22 | "tutor:lessonStarted": { 23 | "@type": "xsd:dateTime" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/solid/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apods: require('./apods.json'), 3 | interop: require('./interop.json'), 4 | notify: require('./notify.json'), 5 | oidc: require('./oidc.json'), 6 | pim: require('./pim.json'), 7 | solid: require('./solid.json') 8 | }; 9 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/solid/oidc.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "oidc", 3 | "namespace": "http://www.w3.org/ns/solid/oidc#", 4 | "jsonldContext": { 5 | "xsd": "http://www.w3.org/2001/XMLSchema#", 6 | "oidc:client_uri": { 7 | "@type": "@id" 8 | }, 9 | "oidc:logo_uri": { 10 | "@type": "@id" 11 | }, 12 | "oidc:policy_uri": { 13 | "@type": "@id" 14 | }, 15 | "oidc:tos_uri": { 16 | "@type": "@id" 17 | }, 18 | "oidc:redirect_uris": { 19 | "@type": "@id" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/solid/pim.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "pim", 3 | "namespace": "http://www.w3.org/ns/pim/space#", 4 | "jsonldContext": { 5 | "pim:storage": { 6 | "@type": "@id" 7 | }, 8 | "pim:preferencesFile": { 9 | "@type": "@id" 10 | }, 11 | "pim:workspace": { 12 | "@type": "@id" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/ontologies/solid/solid.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "solid", 3 | "namespace": "http://www.w3.org/ns/solid/terms#", 4 | "jsonldContext": { 5 | "solid:publicTypeIndex": { 6 | "@type": "@id" 7 | }, 8 | "solid:privateTypeIndex": { 9 | "@type": "@id" 10 | }, 11 | "solid:hasTypeRegistration": { 12 | "@type": "@id" 13 | }, 14 | "solid:forClass": { 15 | "@type": "@id" 16 | }, 17 | "solid:instance": { 18 | "@type": "@id" 19 | }, 20 | "solid:instanceContainer": { 21 | "@type": "@id" 22 | }, 23 | "solid:oidcIssuer": { 24 | "@type": "@id" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/ontologies", 3 | "version": "1.1.3", 4 | "description": "SemApps ontologies", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/triplestore": "1.1.3", 9 | "moleculer-db": "^0.8.16", 10 | "node-fetch": "^2.6.6" 11 | }, 12 | "publishConfig": { 13 | "access": "public" 14 | }, 15 | "engines": { 16 | "node": ">=14" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/middleware/packages/ontologies/utils.js: -------------------------------------------------------------------------------- 1 | const arrayOf = value => { 2 | // If the field is null-ish, we suppose there are no values. 3 | if (value === null || value === undefined) { 4 | return []; 5 | } 6 | // Return as is. 7 | if (Array.isArray(value)) { 8 | return value; 9 | } 10 | // Single value is made an array. 11 | return [value]; 12 | }; 13 | 14 | const isURL = value => (typeof value === 'string' || value instanceof String) && value.startsWith('http'); 15 | 16 | module.exports = { 17 | arrayOf, 18 | isURL 19 | }; 20 | -------------------------------------------------------------------------------- /src/middleware/packages/solid/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/solid 2 | 3 | Solid module for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/solid) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/solid/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | StorageService: require('./services/storage'), 3 | EndpointService: require('./services/endpoint'), 4 | NotificationsProviderService: require('./services/notifications/provider'), 5 | NotificationsListenerService: require('./services/notifications/listener'), 6 | PreferencesFileService: require('./services/preferences-file'), 7 | TypeIndexesService: require('./services/type-index/type-indexes') 8 | }; 9 | -------------------------------------------------------------------------------- /src/middleware/packages/solid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/solid", 3 | "version": "1.1.3", 4 | "description": "Solid module for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@rdfjs/data-model": "^1.3.4", 9 | "@semapps/activitypub": "1.1.3", 10 | "@semapps/ldp": "1.1.3", 11 | "@semapps/middlewares": "1.1.3", 12 | "@semapps/mime-types": "1.1.3", 13 | "@semapps/ontologies": "1.1.3", 14 | "@semapps/triplestore": "1.1.3", 15 | "@semapps/webid": "1.1.3", 16 | "http-link-header": "^1.1.1", 17 | "moleculer": "^0.14.19", 18 | "moleculer-bull": "^0.2.5", 19 | "moleculer-db": "^0.8.16", 20 | "moleculer-web": "^0.10.0-beta1", 21 | "moment": "2.30.1", 22 | "node-fetch": "^2.6.6", 23 | "url-join": "^4.0.1", 24 | "uuid": "^9.0.1" 25 | }, 26 | "publishConfig": { 27 | "access": "public" 28 | }, 29 | "engines": { 30 | "node": ">=14" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/middleware/packages/solid/services/endpoint.js: -------------------------------------------------------------------------------- 1 | const { SpecialEndpointMixin } = require('@semapps/ldp'); 2 | 3 | module.exports = { 4 | name: 'solid-endpoint', 5 | mixins: [SpecialEndpointMixin], 6 | settings: { 7 | baseUrl: null, 8 | settingsDataset: null, 9 | endpoint: { 10 | path: '/.well-known/solid', 11 | initialData: { 12 | type: 'http://www.w3.org/ns/pim/space#Storage' 13 | } 14 | } 15 | }, 16 | dependencies: ['api', 'ldp'], 17 | async started() { 18 | await this.broker.call('ldp.link-header.register', { actionName: 'solid-endpoint.getLink' }); 19 | }, 20 | actions: { 21 | getLink() { 22 | return { 23 | uri: this.endpointUrl, 24 | rel: 'http://www.w3.org/ns/solid/terms#storageDescription' 25 | }; 26 | } 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/middleware/packages/sparql-endpoint/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/sparql-endpoint 2 | 3 | SPARQL endpoint for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/sparql-endpoint) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/sparql-endpoint/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SparqlEndpointService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/sparql-endpoint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/sparql-endpoint", 3 | "version": "1.1.3", 4 | "description": "SPARQL endpoint for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@rdfjs/data-model": "^1.3.4", 9 | "@semapps/middlewares": "1.1.3", 10 | "@semapps/mime-types": "1.1.3", 11 | "@semapps/triplestore": "1.1.3", 12 | "moleculer": "^0.14.18", 13 | "moleculer-web": "^0.10.0-beta1", 14 | "url-join": "^4.0.1" 15 | }, 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "gitHead": "684ba335d0759920f4134f550431b3c3af8e2599", 20 | "engines": { 21 | "node": ">=14" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/middleware/packages/sync/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/sync 2 | 3 | Synchronization tools for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/sync/index) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/sync/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ObjectsWatcherMiddleware: require('./middlewares/objects-watcher'), 3 | AggregatorService: require('./services/aggregator'), 4 | MirrorService: require('./services/mirror'), 5 | SynchronizerService: require('./services/synchronizer') 6 | }; 7 | -------------------------------------------------------------------------------- /src/middleware/packages/sync/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/sync", 3 | "version": "1.1.3", 4 | "description": "Synchronization tools for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/activitypub": "1.1.3", 9 | "@semapps/ldp": "1.1.3", 10 | "@semapps/mime-types": "1.1.3", 11 | "moleculer": "^0.14.17", 12 | "node-fetch": "^2.6.6", 13 | "url-join": "^4.0.1" 14 | }, 15 | "publishConfig": { 16 | "access": "public" 17 | }, 18 | "engines": { 19 | "node": ">=14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/middleware/packages/triplestore/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/triplestore 2 | 3 | Triple store module for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/triplestore) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/triplestore/actions/dropAll.js: -------------------------------------------------------------------------------- 1 | const urlJoin = require('url-join'); 2 | 3 | module.exports = { 4 | visibility: 'public', 5 | params: { 6 | webId: { 7 | type: 'string', 8 | optional: true 9 | }, 10 | dataset: { 11 | type: 'string', 12 | optional: true 13 | } 14 | }, 15 | async handler(ctx) { 16 | const webId = ctx.params.webId || ctx.meta.webId || 'anon'; 17 | const dataset = ctx.params.dataset || ctx.meta.dataset || this.settings.mainDataset; 18 | 19 | if (!(await ctx.call('triplestore.dataset.exist', { dataset }))) 20 | throw new Error(`The dataset ${dataset} doesn't exist`); 21 | 22 | return await this.fetch(urlJoin(this.settings.url, dataset, 'update'), { 23 | body: 'update=CLEAR+ALL', 24 | headers: { 25 | 'Content-Type': 'application/x-www-form-urlencoded', 26 | 'X-SemappsUser': webId 27 | } 28 | }); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/middleware/packages/triplestore/index.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils'); 2 | 3 | module.exports = { 4 | DatasetService: require('./subservices/dataset'), 5 | TripleStoreAdapter: require('./adapter'), 6 | TripleStoreService: require('./service'), 7 | ...utils 8 | }; 9 | -------------------------------------------------------------------------------- /src/middleware/packages/triplestore/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/triplestore", 3 | "version": "1.1.3", 4 | "description": "Triple store module for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/middlewares": "1.1.3", 9 | "@semapps/mime-types": "1.1.3", 10 | "jsonld": "^3.3.2", 11 | "moleculer": "^0.14.29", 12 | "negotiator": "^0.6.2", 13 | "node-fetch": "^2.6.6", 14 | "sparqljs": "^3.5.2", 15 | "sparqljson-parse": "^1.5.1", 16 | "string-template": "^1.0.0", 17 | "url-join": "^4.0.1", 18 | "uuid": "^9.0.1" 19 | }, 20 | "publishConfig": { 21 | "access": "public" 22 | }, 23 | "gitHead": "06cb2decdab424e8686a5d77cc3364fbf1912439", 24 | "engines": { 25 | "node": ">=14" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/middleware/packages/void/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/void 2 | 3 | Void module for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/mirror/index) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/void/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | VoidService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/void/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/void", 3 | "version": "1.1.3", 4 | "description": "Void module for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/ldp": "1.1.3", 9 | "@semapps/middlewares": "1.1.3", 10 | "@semapps/mime-types": "1.1.3", 11 | "@semapps/ontologies": "1.1.3", 12 | "jsonld-streaming-serializer": "^1.2.0", 13 | "moleculer": "^0.14.17", 14 | "n3": "^1.8.0", 15 | "url-join": "^4.0.1" 16 | }, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "engines": { 21 | "node": ">=14" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/webacl 2 | 3 | WebACL service for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/webacl/index) -------------------------------------------------------------------------------- /src/middleware/packages/webacl/index.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils'); 2 | 3 | module.exports = { 4 | GroupsManagerBot: require('./bots/groups-manager'), 5 | AuthorizerBot: require('./bots/authorizer'), 6 | WebAclService: require('./service'), 7 | WebAclMiddleware: require('./middlewares/webacl'), 8 | CacherMiddleware: require('./middlewares/cacher'), 9 | ...utils 10 | }; 11 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/middlewares/cacher.js: -------------------------------------------------------------------------------- 1 | const { Cachers } = require('moleculer'); 2 | 3 | let cacher; 4 | 5 | // It has been suggested to put this middleware in Moleculer core code: 6 | // https://github.com/moleculerjs/moleculer/issues/892 7 | const CacherMiddleware = opts => ({ 8 | name: 'CacherMiddleware', 9 | created(broker) { 10 | if (opts) { 11 | broker.cacher = Cachers.resolve(opts); 12 | broker.cacher.init(broker); 13 | cacher = broker.cacher.middleware(); 14 | } 15 | }, 16 | // TODO see why this is not called by Moleculer 17 | // async stopped(broker) { 18 | // if (opts) { 19 | // await broker.cacher.close(); 20 | // } 21 | // }, 22 | localAction(next, action) { 23 | if (cacher) { 24 | return cacher.localAction(next, action); 25 | } 26 | return next; 27 | } 28 | }); 29 | 30 | module.exports = CacherMiddleware; 31 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/services/group/actions/getUri.js: -------------------------------------------------------------------------------- 1 | const urlJoin = require('url-join'); 2 | 3 | module.exports = { 4 | action: { 5 | visibility: 'public', 6 | params: { 7 | groupSlug: { type: 'string', optional: false, trim: true } 8 | }, 9 | async handler(ctx) { 10 | const { groupSlug } = ctx.params; 11 | return urlJoin(this.settings.baseUrl, '_groups', groupSlug); 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/services/resource/actions/deleteAllRights.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | action: { 3 | visibility: 'public', 4 | params: { 5 | resourceUri: { type: 'string', optional: false } 6 | }, 7 | async handler(ctx) { 8 | const { resourceUri } = ctx.params; 9 | 10 | const isContainer = await ctx.call('ldp.container.exist', { containerUri: resourceUri, webId: 'system' }); 11 | 12 | await ctx.call('triplestore.update', { 13 | query: ` 14 | PREFIX acl: 15 | WITH <${this.settings.graphName}> 16 | DELETE { ?auth ?p2 ?o } 17 | WHERE { ?auth ?p <${resourceUri}>. 18 | FILTER (?p IN (acl:accessTo, acl:default ) ) 19 | ?auth ?p2 ?o } 20 | `, 21 | webId: 'system' 22 | }); 23 | 24 | ctx.emit( 25 | 'webacl.resource.deleted', 26 | { uri: resourceUri, dataset: ctx.meta.dataset, isContainer }, 27 | { meta: { webId: null, dataset: null } } 28 | ); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/services/resource/actions/deleteAllUserRights.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | action: { 3 | visibility: 'public', 4 | params: { 5 | webId: { type: 'string', optional: false } 6 | }, 7 | async handler(ctx) { 8 | const { webId } = ctx.params; 9 | 10 | await ctx.call('triplestore.update', { 11 | query: ` 12 | PREFIX acl: 13 | WITH <${this.settings.graphName}> 14 | DELETE { ?auth acl:agent <${webId}> } 15 | WHERE { ?auth acl:agent <${webId}> } 16 | `, 17 | webId: 'system' 18 | }); 19 | 20 | ctx.emit( 21 | 'webacl.resource.user-deleted', 22 | { webId, dataset: ctx.meta.dataset }, 23 | { meta: { webId: null, dataset: null } } 24 | ); 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/services/resource/actions/getLink.js: -------------------------------------------------------------------------------- 1 | const { getAclUriFromResourceUri } = require('../../../utils'); 2 | 3 | module.exports = { 4 | action: { 5 | visibility: 'public', 6 | params: { 7 | uri: { type: 'string', optional: false } 8 | }, 9 | handler(ctx) { 10 | const { uri } = ctx.params; 11 | return { 12 | uri: getAclUriFromResourceUri(this.settings.baseUrl, uri), 13 | rel: 'acl' 14 | }; 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/middleware/packages/webacl/services/resource/actions/isPublic.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | action: { 3 | visibility: 'public', 4 | params: { 5 | resourceUri: { type: 'string' } 6 | }, 7 | async handler(ctx) { 8 | const { resourceUri } = ctx.params; 9 | const { read } = await ctx.call('webacl.resource.hasRights', { 10 | resourceUri, 11 | rights: { read: true }, 12 | webId: 'anon' 13 | }); 14 | return read; 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/middleware/packages/webfinger/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/webfinger 2 | 3 | Webfinger extension for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/webfinger) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/webfinger/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | WebfingerService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/webfinger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/webfinger", 3 | "version": "1.1.3", 4 | "description": "Webfinger extension for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/mime-types": "1.1.3", 9 | "node-fetch": "^2.6.6" 10 | }, 11 | "publishConfig": { 12 | "access": "public" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/middleware/packages/webhooks/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/webhooks 2 | 3 | Incoming webhooks for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/webhooks) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/webhooks/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | WebhooksService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/webhooks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/webhooks", 3 | "version": "1.1.3", 4 | "description": "Incoming webhooks for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/ldp": "1.0.10", 9 | "@semapps/triplestore": "1.0.10", 10 | "moleculer": "^0.14.18", 11 | "moleculer-db": "^0.8.15", 12 | "url-join": "^4.0.1" 13 | }, 14 | "publishConfig": { 15 | "access": "public" 16 | }, 17 | "gitHead": "06cb2decdab424e8686a5d77cc3364fbf1912439", 18 | "engines": { 19 | "node": ">=14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/middleware/packages/webid/README.md: -------------------------------------------------------------------------------- 1 | # @semapps/webid 2 | 3 | WebID service for SemApps 4 | 5 | [Documentation](https://semapps.org/docs/middleware/webid) 6 | -------------------------------------------------------------------------------- /src/middleware/packages/webid/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | WebIdService: require('./service') 3 | }; 4 | -------------------------------------------------------------------------------- /src/middleware/packages/webid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@semapps/webid", 3 | "version": "1.1.3", 4 | "description": "WebID service for SemApps", 5 | "license": "Apache-2.0", 6 | "author": "Virtual Assembly", 7 | "dependencies": { 8 | "@semapps/activitypub": "1.1.3", 9 | "@semapps/ldp": "1.1.3", 10 | "@semapps/mime-types": "1.1.3", 11 | "@semapps/ontologies": "1.1.3", 12 | "url-join": "^4.0.1" 13 | }, 14 | "publishConfig": { 15 | "access": "public" 16 | }, 17 | "gitHead": "f65a5a67d02782b0539d12ed482e8cc4149e5d36", 18 | "engines": { 19 | "node": ">=14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/middleware/tests/.env: -------------------------------------------------------------------------------- 1 | SEMAPPS_HOME_URL=http://localhost:3000/ 2 | 3 | SEMAPPS_ACTIVATE_CACHE=false 4 | 5 | # Fuseki instance with ACL 6 | SEMAPPS_SPARQL_ENDPOINT=http://localhost:3040/ 7 | SEMAPPS_MAIN_DATASET=testData 8 | SEMAPPS_SETTINGS_DATASET=settings_test 9 | SEMAPPS_JENA_USER=admin 10 | SEMAPPS_JENA_PASSWORD=admin 11 | 12 | # Fuseki instance without ACL 13 | SEMAPPS_NO_ACL_SPARQL_ENDPOINT=http://localhost:3050/ 14 | SEMAPPS_NO_ACL_MAIN_DATASET=testData 15 | SEMAPPS_NO_ACL_JENA_USER=admin 16 | SEMAPPS_NO_ACL_JENA_PASSWORD=admin 17 | -------------------------------------------------------------------------------- /src/middleware/tests/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { "node/no-extraneous-require": "off", "no-plusplus": "off", "global-require": "off" } 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/tests/.gitignore: -------------------------------------------------------------------------------- 1 | /data 2 | /uploads 3 | 4 | .env.local 5 | 6 | */actors/ 7 | */jwt/*.key 8 | */jwt/*.key.pub 9 | 10 | /actors/ 11 | /jwt/*.key 12 | /jwt/*.key.pub 13 | -------------------------------------------------------------------------------- /src/middleware/tests/activitypub/data/actor1.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "alice", 3 | "email": "alice@test.com", 4 | "password": "test", 5 | "name": "Alice" 6 | } 7 | -------------------------------------------------------------------------------- /src/middleware/tests/activitypub/data/actor2.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "bob", 3 | "email": "bob@test.com", 4 | "password": "test", 5 | "name": "Bob" 6 | } 7 | -------------------------------------------------------------------------------- /src/middleware/tests/activitypub/jwt/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/middleware/tests/activitypub/jwt/.gitkeep -------------------------------------------------------------------------------- /src/middleware/tests/config.js: -------------------------------------------------------------------------------- 1 | // Read all .env* files in the root folder and add them to process.env 2 | // See https://github.com/kerimdzhanov/dotenv-flow for more details 3 | require('dotenv-flow').config(); 4 | 5 | module.exports = { 6 | HOME_URL: process.env.SEMAPPS_HOME_URL, 7 | SPARQL_ENDPOINT: process.env.SEMAPPS_SPARQL_ENDPOINT, 8 | MAIN_DATASET: process.env.SEMAPPS_MAIN_DATASET, 9 | SETTINGS_DATASET: process.env.SEMAPPS_SETTINGS_DATASET, 10 | JENA_USER: process.env.SEMAPPS_JENA_USER, 11 | JENA_PASSWORD: process.env.SEMAPPS_JENA_PASSWORD, 12 | ACTIVATE_CACHE: process.env.SEMAPPS_ACTIVATE_CACHE === 'true', 13 | FUSEKI_BASE: process.env.FUSEKI_BASE 14 | }; 15 | -------------------------------------------------------------------------------- /src/middleware/tests/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | fuseki_tests: 3 | image: semapps/jena-fuseki-webacl 4 | container_name: fuseki_tests 5 | restart: always 6 | volumes: 7 | - ./data/fuseki_tests:/fuseki:z 8 | ports: 9 | - '3040:3030' 10 | expose: 11 | - '3040' 12 | environment: 13 | ADMIN_PASSWORD: 'admin' 14 | 15 | redis: 16 | image: redis 17 | container_name: redis_middleware_tests 18 | expose: 19 | - '6379' 20 | ports: 21 | - '6379:6379' 22 | volumes: 23 | - ./data/redis:/data:z 24 | command: ['redis-server', '--appendonly', 'yes'] 25 | 26 | arena: 27 | image: activitypods/arena 28 | container_name: arena_tests 29 | restart: always 30 | volumes: 31 | - ./arena.json:/opt/arena/src/server/config/index.json:z 32 | depends_on: 33 | - redis 34 | ports: 35 | - '4567:4567' 36 | expose: 37 | - '4567' 38 | environment: 39 | REDIS_HOST: 'redis' 40 | networks: 41 | default: 42 | name: middleware_tests_network 43 | -------------------------------------------------------------------------------- /src/middleware/tests/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | const config = { 3 | testEnvironment: 'node', 4 | transform: { 5 | '\\.[jt]sx?$': ['esbuild-jest', { rootMode: 'upward' }] 6 | }, 7 | transformIgnorePatterns: [], 8 | setupFilesAfterEnv: ['/jest.setup.js'] 9 | }; 10 | 11 | module.exports = config; 12 | -------------------------------------------------------------------------------- /src/middleware/tests/jest.setup.js: -------------------------------------------------------------------------------- 1 | expect.extend({ 2 | //An assertion to check if a value is undefined or an empty array 3 | toBeUndefinedOrEmptyArray(received) { 4 | const pass = received === undefined || (Array.isArray(received) && received.length === 0); 5 | if (pass) { 6 | return { 7 | message: () => `expected ${received} not to be undefined or an empty array`, 8 | pass: true 9 | }; 10 | } else { 11 | return { 12 | message: () => `expected ${received} to be undefined or an empty array`, 13 | pass: false 14 | }; 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /src/middleware/tests/jsonld/contexts/ontology1.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "ont1": "https://www.w3.org/ns/ontology1#", 4 | "label": { 5 | "@id": "ont1:label" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/middleware/tests/jsonld/contexts/ontology2.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "ont2": "https://www.w3.org/ns/ontology2#" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/middleware/tests/ldp/av-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/src/middleware/tests/ldp/av-icon.png -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/contexts/ontology1.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "ont1": "https://www.w3.org/ns/ontology1#", 4 | "label": { 5 | "@id": "ont1:label" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/contexts/ontology2.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "ont2": "https://www.w3.org/ns/ontology2#" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/ontologies/ont1.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "ont1", 3 | "namespace": "https://www.w3.org/ns/ontology1#", 4 | "jsonldContext": "https://www.w3.org/ns/ontology1.jsonld", 5 | "preserveContextUri": true 6 | } 7 | -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/ontologies/ont2.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "ont2", 3 | "namespace": "https://www.w3.org/ns/ontology2#", 4 | "jsonldContext": "https://www.w3.org/ns/ontology2.jsonld" 5 | } 6 | -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/ontologies/ont3.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "ont3", 3 | "namespace": "https://www.w3.org/ns/ontology3#", 4 | "jsonldContext": { 5 | "friend": { 6 | "@id": "ont3:friend", 7 | "@type": "@id", 8 | "@protected": true 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/ontologies/ont4.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "ont4", 3 | "namespace": "https://www.w3.org/ns/ontology4#" 4 | } 5 | -------------------------------------------------------------------------------- /src/middleware/tests/ontologies/ontologies/ont5.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "ont5", 3 | "namespace": "https://www.w3.org/ns/ontology5#", 4 | "jsonldContext": { 5 | "friend": { 6 | "@id": "ont5:friend", 7 | "@type": "@id" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/middleware/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext"], 4 | "allowJs": true, 5 | "checkJs": false, 6 | "resolveJsonModule": true, 7 | "declaration": true, 8 | "noEmit": true, 9 | "noLib": false, 10 | "skipLibCheck": true, 11 | "sourceMap": true, 12 | "strictNullChecks": true, 13 | "module": "NodeNext", 14 | "moduleResolution": "NodeNext", 15 | "resolvePackageJsonExports": true, 16 | "esModuleInterop": true, 17 | "resolvePackageJsonImports": true 18 | }, 19 | "include": ["**/*.js", "**/*.ts"], 20 | "exclude": [] 21 | } 22 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | .now -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /website/docs/frontend/images/multiurlfield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/frontend/images/multiurlfield.png -------------------------------------------------------------------------------- /website/docs/frontend/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | Although the core of SemApps is its middleware, we offer frontend components to facilitate the development of interfaces 6 | that connect to servers conforming to semantic web standards (LDP, SPARQL, WAC...) 7 | 8 | We rely on [React-Admin](https://marmelab.com/react-admin/doc/3.19/Readme.html), which is a robust and well maintained 9 | framework. It is based on [Material-UI](https://v4.mui.com/), which offers very advanced customization and theming 10 | possibilities. 11 | 12 | The core pieces we offer are: 13 | - A [Semantic Data Provider](semantic-data-provider/index.md), which is the piece connecting the React-Admin interface with the Semantic Server. 14 | - An [Auth Provider](auth-provider.md) to allow users to identify themselves. 15 | 16 | In the future we may propose packages for other types of frontend frameworks. 17 | -------------------------------------------------------------------------------- /website/docs/guides/activitypub_resources/loophole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/activitypub_resources/loophole.png -------------------------------------------------------------------------------- /website/docs/guides/activitypub_resources/mastodon-follower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/activitypub_resources/mastodon-follower.png -------------------------------------------------------------------------------- /website/docs/guides/activitypub_resources/mastodon-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/activitypub_resources/mastodon-note.png -------------------------------------------------------------------------------- /website/docs/guides/dms_resources/homepage_dms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/dms_resources/homepage_dms.png -------------------------------------------------------------------------------- /website/docs/guides/ldp_resources/jenafuseki_localData.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/ldp_resources/jenafuseki_localData.jpg -------------------------------------------------------------------------------- /website/docs/guides/ldp_resources/moleculer-repl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/ldp_resources/moleculer-repl.png -------------------------------------------------------------------------------- /website/docs/guides/ldp_resources/query_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/docs/guides/ldp_resources/query_result.png -------------------------------------------------------------------------------- /website/docs/middleware/ldp/document-tagger.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: DocumentTaggerMixin 3 | --- 4 | 5 | Tag new and updated resources with the following information: creation date, last modification date, creator's webId. 6 | 7 | By default, the [Dublin Core's ontology](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/), is used but this can be changed with the `documentPredicates` setting (see below). 8 | 9 | ## Usage 10 | 11 | ```js 12 | const { LdpService, DocumentTaggerMixin } = require('@semapps/ldp'); 13 | 14 | module.exports = { 15 | mixins: [LdpService, DocumentTaggerMixin], 16 | settings: { 17 | // Set this if you want to change the default ontology 18 | documentPredicates: { 19 | created: 'http://purl.org/dc/terms/created', 20 | updated: 'http://purl.org/dc/terms/modified', 21 | creator: 'http://purl.org/dc/terms/creator' 22 | } 23 | } 24 | }; 25 | ``` 26 | -------------------------------------------------------------------------------- /website/docs/middleware/notifications/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Notifications 3 | --- 4 | 5 | This package allows you to send notifications to user, through digest emails, single emails or push notifications. 6 | 7 | ## Services 8 | 9 | - [DigestNotificationsService](./digest.md) 10 | - [SingleMailNotificationsService](./single-mail.md) 11 | - ExpoPushService *(legacy, must be refactored)* 12 | 13 | ## Install 14 | 15 | ```bash 16 | $ yarn add @semapps/notifications 17 | ``` 18 | -------------------------------------------------------------------------------- /website/docs/middleware/solid/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Solid 3 | --- 4 | 5 | This package handles standards related to the [Solid](https://solidproject.org/) project. 6 | 7 | ## Services 8 | 9 | - [PodService](pod.md) 10 | - [TypeIndexesService](type-indexes.md) 11 | - [TypeRegistrationsService](type-registrations.md) 12 | - [NotificationsProviderService](notifications-provider.md) 13 | - [NotificationsListenerService](notifications-listener.md) 14 | 15 | ## Install 16 | 17 | ```bash 18 | $ yarn add @semapps/solid 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/others/auth.txt: -------------------------------------------------------------------------------- 1 | first Login without ever existing user 2 | Passport OID Authentificate -> req.user <- oidc userinfo 3 | app selectProfilData -> return profilData from oidc userinfo 4 | app findOrCreateProfil -> create user in user container with app data choose + add webId to req.user 5 | generate Token -> app selectProfilData from oidc userInfo + req.user.webId = payload -> token from payload return to client 6 | 7 | get user info 8 | authenticate or authorize -> ctx.meta.tokenPayload <- token from client 9 | getWebId -> ctx.meta.tokenPayload.webId 10 | return subject 11 | 12 | other fonction (ldp) 13 | authenticate or authorize -> ctx.meta.webId <- token from client 14 | api -> webId in params of service 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /website/docs/triplestore/moving-datasets.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Moving datasets 3 | --- 4 | 5 | Fuseki use [sparse files](https://wiki.archlinux.org/title/Sparse_file) to store datasets. Basically it means datasets appear to take more space than what they are really taking. 6 | 7 | If you want to move them to another server, you will need to ensure whatever method you use will take this into account, otherwise you may find yourself with 20-30 times more data than you initially had. 8 | 9 | For example the `tar` tool has a `-S` option which will look if the files to compress are sparse files and, in that case, only bring into the archive the "real" part of the file. More information [here](https://www.gnu.org/software/tar/manual/html_node/sparse.html). 10 | 11 | The `rsync` tool has a similar `-S` option which do the same. More information [here](https://gergap.wordpress.com/2013/08/10/rsync-and-sparse-files/). 12 | -------------------------------------------------------------------------------- /website/i18n/fr/docusaurus-theme-classic/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": { 3 | "message": "SemApps", 4 | "description": "The title in the navbar" 5 | }, 6 | "item.label.About": { 7 | "message": "A propos de", 8 | "description": "Navbar item with label About" 9 | }, 10 | "item.label.Team": { 11 | "message": "Equipe", 12 | "description": "Navbar item with label Team" 13 | }, 14 | "item.label.Governance": { 15 | "message": "Gouvernance", 16 | "description": "Navbar item with label Governance" 17 | }, 18 | "item.label.Documentation": { 19 | "message": "Documentation", 20 | "description": "Navbar item with label Documentation" 21 | }, 22 | "item.label.How to contribute": { 23 | "message": "Contribuer", 24 | "description": "Navbar item with label How to contribute" 25 | }, 26 | "item.label.Blog": { 27 | "message": "Blog", 28 | "description": "Navbar item with label Blog" 29 | }, 30 | "item.label.GitHub": { 31 | "message": "GitHub", 32 | "description": "Navbar item with label GitHub" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /website/src/pages/base.module.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .layoutContainer { 7 | 8 | --color-white: #f5f5f5; 9 | --color-black: black; 10 | --color-primary: #3AA2A5; 11 | --color-secondary: #282c34; 12 | --color-tertiary: #435B5B; 13 | --color-secondary-darken: #20232a; 14 | 15 | p { 16 | margin: 0; 17 | } 18 | 19 | ol, 20 | ul { 21 | list-style: none; 22 | margin: 0; 23 | padding: 0; 24 | } 25 | } -------------------------------------------------------------------------------- /website/src/pages/index/Tool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AnimationOnScroll } from 'react-animation-on-scroll'; 3 | import "animate.css/animate.min.css"; 4 | import styles from './index.module.scss'; 5 | import CubesIcon from './CubesIcon'; 6 | 7 | const Tool = ({ label, content, link, link2 }) => { 8 | return ( 9 | <> 10 |
11 | 12 |
13 |
14 |

15 | { !!link ? ( 16 | {label} 17 | ) : ( 18 | <>{label} 19 | )} 20 |

21 |
  22 | 23 |
 
24 |
25 |
26 |
{content}
27 |
28 | 29 | ); 30 | }; 31 | 32 | export default Tool; -------------------------------------------------------------------------------- /website/src/pages/index/Website.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AnimationOnScroll } from 'react-animation-on-scroll'; 3 | import "animate.css/animate.min.css"; 4 | import styles from './index.module.scss'; 5 | 6 | const Website = ({ label, image, link }) => { 7 | return ( 8 | <> 9 |
10 | 11 | {label} 12 | 13 |
14 | 15 |

{label}

16 |
17 | 18 | ); 19 | }; 20 | 21 | export default Website; -------------------------------------------------------------------------------- /website/src/pages/team/Subtitle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './team.module.scss'; 3 | import { AnimationOnScroll } from 'react-animation-on-scroll'; 4 | import "animate.css/animate.min.css"; 5 | 6 | const Subtitle = ({ label }) => { 7 | return ( 8 |
9 | 10 |

{label}

11 |
12 |
 
13 |
14 | ); 15 | }; 16 | 17 | export default Subtitle; -------------------------------------------------------------------------------- /website/static/img/100-lieux-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/100-lieux-cover.png -------------------------------------------------------------------------------- /website/static/img/Thomas-Francart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/Thomas-Francart.jpg -------------------------------------------------------------------------------- /website/static/img/activity-pods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/activity-pods.png -------------------------------------------------------------------------------- /website/static/img/activitypub-bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/activitypub-bridge.png -------------------------------------------------------------------------------- /website/static/img/archipelago.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/archipelago.png -------------------------------------------------------------------------------- /website/static/img/aurba-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/aurba-cover.png -------------------------------------------------------------------------------- /website/static/img/av-baniere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/av-baniere.png -------------------------------------------------------------------------------- /website/static/img/av-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/av-icon.png -------------------------------------------------------------------------------- /website/static/img/bastien-siguier.jfif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/bastien-siguier.jfif -------------------------------------------------------------------------------- /website/static/img/bienvenue-chez-moi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/bienvenue-chez-moi.png -------------------------------------------------------------------------------- /website/static/img/blank-profile-picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/blank-profile-picture.png -------------------------------------------------------------------------------- /website/static/img/cdlt-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/cdlt-cover.png -------------------------------------------------------------------------------- /website/static/img/cdlt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/cdlt.jpg -------------------------------------------------------------------------------- /website/static/img/collectif-emploi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/collectif-emploi.png -------------------------------------------------------------------------------- /website/static/img/dreamstime_s_23213432.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/dreamstime_s_23213432.jpg -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/guillaume-rouyer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/guillaume-rouyer.jpg -------------------------------------------------------------------------------- /website/static/img/logo-4ch-fb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-4ch-fb.png -------------------------------------------------------------------------------- /website/static/img/logo-ademe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-ademe.png -------------------------------------------------------------------------------- /website/static/img/logo-afaup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-afaup.png -------------------------------------------------------------------------------- /website/static/img/logo-afaup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-afaup.webp -------------------------------------------------------------------------------- /website/static/img/logo-aurba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-aurba.jpg -------------------------------------------------------------------------------- /website/static/img/logo-aurba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-aurba.png -------------------------------------------------------------------------------- /website/static/img/logo-av.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-av.jpg -------------------------------------------------------------------------------- /website/static/img/logo-cdlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-cdlt.png -------------------------------------------------------------------------------- /website/static/img/logo-classe-dehors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-classe-dehors.png -------------------------------------------------------------------------------- /website/static/img/logo-dfc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-dfc.png -------------------------------------------------------------------------------- /website/static/img/logo-energie-partagee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-energie-partagee.png -------------------------------------------------------------------------------- /website/static/img/logo-flodio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-flodio.png -------------------------------------------------------------------------------- /website/static/img/logo-lacoop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-lacoop.png -------------------------------------------------------------------------------- /website/static/img/logo-petr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-petr.png -------------------------------------------------------------------------------- /website/static/img/logo-petr.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-petr.webp -------------------------------------------------------------------------------- /website/static/img/logo-utt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo-utt.png -------------------------------------------------------------------------------- /website/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo.png -------------------------------------------------------------------------------- /website/static/img/logo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/logo_dark.png -------------------------------------------------------------------------------- /website/static/img/maxime_lecoq.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/maxime_lecoq.jpeg -------------------------------------------------------------------------------- /website/static/img/minicourses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/minicourses.png -------------------------------------------------------------------------------- /website/static/img/niko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/niko.png -------------------------------------------------------------------------------- /website/static/img/organigraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/organigraph.png -------------------------------------------------------------------------------- /website/static/img/pierre-bouvier-muller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/pierre-bouvier-muller.png -------------------------------------------------------------------------------- /website/static/img/react-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | React Logo 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /website/static/img/simon-louvet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/simon-louvet.jpg -------------------------------------------------------------------------------- /website/static/img/srosset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/srosset.jpg -------------------------------------------------------------------------------- /website/static/img/toolbox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/toolbox.jpg -------------------------------------------------------------------------------- /website/static/img/vincent-farcy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/vincent-farcy.png -------------------------------------------------------------------------------- /website/static/img/yannick-duthe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assemblee-virtuelle/semapps/fbe9891f4cc3569fb15d5885236b143ed213a6ed/website/static/img/yannick-duthe.png --------------------------------------------------------------------------------