Files
festipod/backend/services/registration.service.js
T
Sylvain Duchesne e17398d86d T04.f: backend Festipod ActivityPods + dockerisation
- Ajoute la configuration et les services backend (app, actors, registration,
  attendees, contacts, catalog, core auth/nodeinfo/proxy/notification).
- Corrige le démarrage : désactive resourcesWithContainerPath pour éviter le
  conflit entre l'URI de l'acteur applicatif (/as/actor/app) et la route /app.
- Corrige l'URL du dépôt de shapes : https://shapes.activitypods.org/.
- Ajoute backend/Dockerfile et docker-compose.yml racine (frontend + backend).
- Met à jour .env.example racine avec les variables SEMAPPS_* et VITE_BACKEND_*.
- Gates verts : bunx tsc --noEmit (0 erreur) et bun test (50 pass).
2026-10-09 13:51:02 +02:00

98 lines
2.8 KiB
JavaScript

const { ACTIVITY_TYPES, OBJECT_TYPES } = require('@semapps/activitypub');
const { PodActivitiesHandlerMixin } = require('@activitypods/app');
const { arrayOf } = require('@semapps/ldp');
module.exports = {
name: 'registration',
mixins: [PodActivitiesHandlerMixin],
async started() {
this.logger.info('Registration watcher subscribed');
},
activities: {
join: {
match: {
type: ACTIVITY_TYPES.JOIN,
object: {
type: OBJECT_TYPES.EVENT
}
},
async onEmit(ctx, activity, actorUri) {
const event = activity.object;
const organizerUri = event['dc:creator'];
if (!organizerUri) return;
const { body: actor } = await ctx.call('pod-resources.get', { resourceUri: actorUri, actorUri });
if (!actor || !actor['apods:contacts']) return;
const contactsGroupUri = await ctx.call('pod-wac-groups.getUriFromCollectionUri', {
collectionUri: actor['apods:contacts']
});
await ctx.call('pod-wac-groups.addMember', {
groupUri: contactsGroupUri,
memberUri: organizerUri,
actorUri
});
},
async onReceive(ctx, activity, actorUri) {
const event = activity.object;
const attendeesCollectionUri = event['apods:attendees'];
if (!attendeesCollectionUri) {
this.logger.warn(`No attendees collection on ${event.id}, skipping Join`);
return;
}
const attendees = await ctx.call('pod-collections.getItems', {
collectionUri: attendeesCollectionUri,
actorUri
});
if (arrayOf(attendees).includes(activity.actor)) {
this.logger.info(`${activity.actor} is already attending ${event.id}`);
return;
}
await ctx.call('attendees.add', {
collectionUri: attendeesCollectionUri,
itemUri: activity.actor,
actorUri
});
}
},
leave: {
match: {
type: ACTIVITY_TYPES.LEAVE,
object: {
type: OBJECT_TYPES.EVENT
}
},
async onReceive(ctx, activity, actorUri) {
const event = activity.object;
const attendeesCollectionUri = event['apods:attendees'];
if (!attendeesCollectionUri) {
this.logger.warn(`No attendees collection on ${event.id}, skipping Leave`);
return;
}
const attendees = await ctx.call('pod-collections.getItems', {
collectionUri: attendeesCollectionUri,
actorUri
});
if (!arrayOf(attendees).includes(activity.actor)) {
this.logger.info(`${activity.actor} is not attending ${event.id}, skipping Leave`);
return;
}
await ctx.call('attendees.remove', {
collectionUri: attendeesCollectionUri,
itemUri: activity.actor,
actorUri
});
}
}
}
};