func (s roomService) userPowerLevel(room ct.RoomId, user ct.UserId) (int, types.Error) { powerLevels, err := s.powerLevels(room) if err != nil { return 0, err } if userLevel, ok := powerLevels.Users[user.String()]; ok { return userLevel, nil } return powerLevels.UserDefault, nil }
func (s userService) CreateUser(id ct.UserId) types.Error { exists, err := s.users.CreateUser(id) if err != nil { return err } if exists { return types.UserInUseError("user '" + id.String() + "' already exists") } return nil }
func (s roomService) userMembership(room ct.RoomId, user ct.UserId) (types.Membership, types.Error) { state, err := s.rooms.RoomState(room, types.EventTypeMembership, user.String()) if err != nil { return types.MembershipNone, err } if state == nil { return types.MembershipNone, nil } membership, ok := state.Content.(*types.MembershipEventContent) if !ok { panic("invalid membership content, was " + reflect.TypeOf(state.Content).String()) } return membership.Membership, nil }
func (s profileService) UpdateProfile( user, caller ct.UserId, name, avatarUrl *string, ) (types.UserProfile, types.Error) { if user != caller { return types.UserProfile{}, types.ForbiddenError("can't change the profile of other users") } profile, err := s.profiles.Profile(user) if err != nil { return types.UserProfile{}, err } if name != nil { profile.DisplayName = *name } if avatarUrl != nil { profile.AvatarUrl = *avatarUrl } _, err = s.profileSink.SetUserProfile(user, profile) if err != nil { return types.UserProfile{}, err } rooms, err := s.members.Rooms(user) if err != nil { return types.UserProfile{}, err } log.Printf("GOT LE STUFF %s, %#v", user, rooms) for _, room := range rooms { membership, err := s.rooms.RoomState(room, types.EventTypeMembership, user.String()) if err != nil { log.Println("failed to get membership when updating profile: " + err.Error()) continue } content := *membership.Content.(*types.MembershipEventContent) content.UserProfile = &profile state, err := s.rooms.SetRoomState(room, user, &content, user.String()) //TODO: fix race, CAS? if err != nil { log.Println("failed to set membership when updating profile: " + err.Error()) continue } _, err = s.eventSink.Send(state) if err != nil { log.Println("failed to send event when updating profile: " + err.Error()) } } return profile, nil }
func DefaultPowerLevels(creator ct.UserId) *PowerLevelsEventContent { powerLevels := new(PowerLevelsEventContent) powerLevels.Ban = 50 powerLevels.Kick = 50 powerLevels.Invite = 0 powerLevels.Redact = 50 powerLevels.CreateState = 50 powerLevels.EventDefault = 0 powerLevels.Users = UserPowerLevelMap{ creator.String(): 100, } powerLevels.Events = map[string]int{ "m.room.name": 100, "m.room.power_levels": 100, } return powerLevels }
func (s syncService) roomSummary( summary *types.RoomSummary, user ct.UserId, room ct.RoomId, end types.StreamToken, limit uint, ) types.Error { roomSet := map[ct.RoomId]struct{}{ room: struct{}{}, } messages, err := s.messageSource.Range(nil, nil, roomSet, end.MessageIndex, 0, limit) if err != nil { return err } startIndex := end.MessageIndex if len(messages) > 0 { startIndex = messages[0].Index() } start := types.NewStreamToken(startIndex, end.PresenceIndex, end.TypingIndex) eventRange := types.NewEventStreamRange(indexedToEvents(messages), start, end) states, err := s.rooms.EntireRoomState(room) if err != nil { return err } membershipState, err := s.rooms.RoomState(room, types.EventTypeMembership, user.String()) if err != nil { return err } membership := membershipState.Content.(*types.MembershipEventContent).Membership joinRuleState, err := s.rooms.RoomState(room, types.EventTypeJoinRules, "") if err != nil { return err } joinRule := joinRuleState.Content.(*types.JoinRulesEventContent).JoinRule visibility := joinRule.ToVisibility() summary.Membership = membership summary.RoomId = room summary.Messages = eventRange summary.State = states summary.Visibility = visibility return nil }
func (s roomService) CreateRoom( domain string, creator ct.UserId, desc *types.RoomDescription, ) (ct.RoomId, *ct.Alias, types.Error) { var alias *ct.Alias id := ct.NewRoomId(utils.RandomString(16), domain) if desc.Alias != nil { a := ct.NewAlias(*desc.Alias, domain) err := s.aliases.AddAlias(a, id) if err != nil { return ct.RoomId{}, nil, err } alias = &a } exists, err := s.rooms.CreateRoom(id) if exists { return ct.RoomId{}, nil, types.RoomInUseError("room '" + id.String() + "' already exists") } if err != nil { return ct.RoomId{}, nil, err } s.members.AddMember(id, creator) _, err = s.sendMessage(id, creator, &types.CreateEventContent{creator}) if err != nil { return ct.RoomId{}, nil, err } _, err = s.setState(id, creator, &types.CreateEventContent{creator}, "") if err != nil { return ct.RoomId{}, nil, err } profile, err := s.profileProvider.Profile(creator) if err != nil { return ct.RoomId{}, nil, err } membership := &types.MembershipEventContent{&profile, types.MembershipMember} _, err = s.setState(id, creator, membership, creator.String()) if err != nil { return ct.RoomId{}, nil, err } _, err = s.setState(id, creator, types.DefaultPowerLevels(creator), "") if err != nil { return ct.RoomId{}, nil, err } joinRuleContent := types.JoinRulesEventContent{desc.Visibility.ToJoinRule()} _, err = s.setState(id, creator, &joinRuleContent, "") if err != nil { return ct.RoomId{}, nil, err } if alias != nil { _, err = s.setState(id, creator, &types.AliasesEventContent{[]ct.Alias{*alias}}, "") if err != nil { return ct.RoomId{}, nil, err } } if desc.Name != nil { _, err = s.setState(id, creator, &types.NameEventContent{*desc.Name}, "") if err != nil { return ct.RoomId{}, nil, err } } if desc.Topic != nil { _, err = s.setState(id, creator, &types.TopicEventContent{*desc.Topic}, "") if err != nil { return ct.RoomId{}, nil, err } } for _, invited := range desc.Invited { membership := types.MembershipEventContent{nil, types.MembershipInvited} _, err = s.setState(id, creator, &membership, invited.String()) if err != nil { return ct.RoomId{}, nil, err } } return id, alias, nil }
func (s roomService) doMembershipChange( room ct.RoomId, caller ct.UserId, user ct.UserId, membership *types.MembershipEventContent, ) (*types.State, types.Error) { log.Printf("attempting membership change of %s in %s to %s, by %s", user, room, membership.Membership, caller) currentMembership, err := s.userMembership(room, user) if err != nil { return nil, err } if currentMembership == membership.Membership { return nil, types.ForbiddenError("membership change was a no-op") } membership.UserProfile = nil switch membership.Membership { case types.MembershipNone: if currentMembership != types.MembershipBanned { return nil, types.BadJsonError("invalid or missing membership in membership change") } err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { return pl.Ban }) if err != nil { return nil, err } if user == caller { return nil, types.ForbiddenError("cannot remove a ban from self") } case types.MembershipInvited: if currentMembership != types.MembershipNone { return nil, types.ForbiddenError("could not invite user to room, already have membership '" + currentMembership.String() + "'") } ok, err := s.allowsJoinRule(room, types.JoinRuleInvite) if err != nil { return nil, err } if !ok { return nil, types.ForbiddenError("room does not allow join method: " + types.JoinRuleInvite.String()) } err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { return pl.Invite }) if err != nil { return nil, err } case types.MembershipMember: switch currentMembership { case types.MembershipNone: ok, err := s.allowsJoinRule(room, types.JoinRulePublic) if err != nil { return nil, err } if !ok { return nil, types.ForbiddenError("room does not allow join method: " + types.JoinRuleInvite.String()) } case types.MembershipInvited: if user != caller { return nil, types.ForbiddenError("cannot force other users to join the room") } case types.MembershipKnocking: if user == caller { return nil, types.ForbiddenError("cannot let yourself in after knocking") } err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { return pl.Invite }) if err != nil { return nil, err } case types.MembershipBanned: if user == caller { return nil, types.ForbiddenError("you are banned from that room") } else { return nil, types.ForbiddenError("that user is banned from this room") } } profile, err := s.profileProvider.Profile(caller) if err != nil { return nil, err } membership.UserProfile = &profile case types.MembershipKnocking: if user != caller { return nil, types.ForbiddenError("cannot force other users to knock") } if currentMembership != types.MembershipNone { return nil, types.ForbiddenError("could not knock on room, already have membership '" + currentMembership.String() + "'") } ok, err := s.allowsJoinRule(room, types.JoinRuleKnock) if err != nil { return nil, err } if !ok { return nil, types.ForbiddenError("room does not allow join method: " + types.JoinRuleKnock.String()) } case types.MembershipLeaving: if currentMembership == types.MembershipNone { return nil, types.ForbiddenError("tried to leave a room without current membership") } if currentMembership == types.MembershipBanned { return nil, types.ForbiddenError("tried to leave room with current membership '" + types.MembershipBanned.String() + "'") } if user != caller { err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { return pl.Kick }) if err != nil { return nil, err } } case types.MembershipBanned: if user == caller { return nil, types.ForbiddenError("cannot ban self") } err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { return pl.Ban }) if err != nil { return nil, err } } if membership.Membership == types.MembershipMember { if err := s.members.AddMember(room, user); err != nil { return nil, err } } else if currentMembership == types.MembershipMember { if err := s.members.RemoveMember(room, user); err != nil { return nil, err } } return s.setState(room, caller, membership, user.String()) }