Exemple #1
0
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
}
Exemple #2
0
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
}
Exemple #3
0
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
}
Exemple #4
0
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
}
Exemple #5
0
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
}
Exemple #6
0
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
}
Exemple #7
0
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
}
Exemple #8
0
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())
}