package setup import ( "context" "errors" "fmt" "log/slog" "github.com/dariuszjaniak/warp/server/internal/appservice" "github.com/dariuszjaniak/warp/server/internal/config" "github.com/dariuszjaniak/warp/server/internal/matrix/event" "github.com/dariuszjaniak/warp/server/internal/roomserver" "github.com/dariuszjaniak/warp/server/internal/userapi" ) // loadAppServices reads the registration files the config names. func loadAppServices(cfg *config.Config) (*appservice.Registry, error) { regs := make([]*appservice.Registration, 0, len(cfg.AppService.ConfigFiles)) for _, path := range cfg.AppService.ConfigFiles { reg, err := appservice.LoadRegistration(path, cfg.Global.ServerName) if err != nil { return nil, err } regs = append(regs, reg) } return appservice.NewRegistry(cfg.Global.ServerName, regs) } // ensureAppServiceSenders creates the sender user of every application // service that does not have one yet. A service acts as its sender // whenever it does not ask to act as somebody else, so the account has to // exist before the first request; it has no password, because nobody logs // in as it. func ensureAppServiceSenders(ctx context.Context, users *userapi.API, registry *appservice.Registry, log *slog.Logger) error { for _, svc := range registry.Services() { _, err := users.CreateAccount(ctx, userapi.NewAccountRequest{Localpart: svc.SenderLocalpart}) switch { case err == nil: log.Info("created the sender of an application service", "appservice", svc.ID, "user_id", svc.SenderUserID()) case errors.Is(err, userapi.ErrUserExists): default: return fmt.Errorf("create the sender of application service %q: %w", svc.ID, err) } } return nil } // roomLeaver is the roomserver's side of a deactivation: the user leaves // every room they are in, rejects every invite and withdraws every knock. // A room that refuses is logged and skipped; the account is already // deactivated, and one stuck room must not keep the user in all the // others. type roomLeaver struct { rooms *roomserver.API log *slog.Logger } // AccountDeactivated implements userapi.AccountObserver. func (l roomLeaver) AccountDeactivated(ctx context.Context, localpart string) { userID := "@" + localpart + ":" + l.rooms.ServerName() memberships, err := l.rooms.UserMemberships(ctx, userID, []string{event.MembershipJoin, event.MembershipInvite, event.MembershipKnock}) if err != nil { l.log.Error("could not list the rooms of a deactivated user", "user_id", userID, "error", err) return } for _, m := range memberships { if err := l.rooms.LeaveRoom(ctx, m.RoomID, userID, ""); err != nil { l.log.Warn("a deactivated user could not leave a room", "user_id", userID, "room_id", m.RoomID, "error", err) } } }