Пример #1
0
func (e authEndpoint) loginWithPassword(hostname string, body *authRequest) interface{} {
	if body.Username == "" {
		return types.BadJsonError("Missing or invalid user")
	}
	if body.Password == "" {
		return types.BadJsonError("Missing or invalid password")
	}
	user := ct.NewUserId(body.Username, hostname)
	exists, err := e.userService.UserExists(user, user)
	if err != nil {
		return err
	}
	if !exists {
		return types.NotFoundError("user '" + user.String() + "' doesn't exist")
	}
	verified, err := e.userService.VerifyPassword(user, body.Password)
	if err != nil {
		return err
	}
	if !verified {
		return types.ForbiddenError("invalid credentials")
	}
	accessToken, err := e.tokenService.NewAccessToken(user)
	if err != nil {
		return err
	}
	return authResponse{
		UserId:      user,
		AccessToken: accessToken.String(),
	}
}
Пример #2
0
func (s userService) SetPassword(user, caller ct.UserId, password string) types.Error {
	if user != caller {
		return types.ForbiddenError("can't change the password of other users")
	}
	hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
	if err != nil {
		return types.ServerError("failed to generate password: " + err.Error())
	}
	if err := s.users.SetUserPasswordHash(user, string(hash)); err != nil {
		return err
	}
	return nil
}
Пример #3
0
func (s roomService) allowsJoinRule(room ct.RoomId, joinRule types.JoinRule) (bool, types.Error) {
	state, err := s.rooms.RoomState(room, types.EventTypeJoinRules, "")
	if err != nil {
		return false, err
	}
	if state == nil {
		panic("room power levels are invalid or missing: " + room.String())
	}
	joinRules, ok := state.Content.(*types.JoinRulesEventContent)
	if !ok {
		panic("invalid join rule content, was " + reflect.TypeOf(state.Content).String())
	}
	if joinRules.JoinRule != joinRule {
		return false, types.ForbiddenError("room does not allow join rule: " + joinRule.String())
	}
	return true, nil
}
Пример #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
}
Пример #5
0
func (s roomService) State(
	room ct.RoomId,
	caller ct.UserId,
	eventType, stateKey string,
) (*types.State, types.Error) {
	membership, err := s.userMembership(room, caller)
	if err != nil {
		return nil, err
	}
	if membership != types.MembershipMember {
		return nil, types.ForbiddenError("cannot read room state, not a member")
	}
	state, err := s.rooms.RoomState(room, eventType, stateKey)
	if err != nil {
		return nil, err
	}
	return state, err
}
Пример #6
0
func (s roomService) testPowerLevel(
	room ct.RoomId,
	user ct.UserId,
	powerLevelFunc func(*types.PowerLevelsEventContent) int,
) types.Error {
	powerLevels, err := s.powerLevels(room)
	if err != nil {
		return err
	}
	userPowerLevel, err := s.userPowerLevel(room, user)
	if err != nil {
		return err
	}
	requiredPowerLevel := powerLevelFunc(powerLevels)
	if userPowerLevel < requiredPowerLevel {
		msg := fmt.Sprintf("not enough power level to perform action (%d < %d)", userPowerLevel, requiredPowerLevel)
		return types.ForbiddenError(msg)
	}
	return nil
}
Пример #7
0
func (s roomService) AddMessage(
	room ct.RoomId,
	caller ct.UserId,
	content types.TypedContent,
) (*types.Message, types.Error) {
	eventType := content.GetEventType()
	if _, ok := disallowedMessageTypes[eventType]; ok {
		return nil, types.ForbiddenError("sending a message event of the type " + eventType + " is not permitted")
	}

	err := s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int {
		if eventLevel, ok := pl.Events[eventType]; ok {
			return eventLevel
		}
		return pl.EventDefault
	})
	if err != nil {
		return nil, err
	}

	return s.sendMessage(room, caller, content)
}
Пример #8
0
func (s presenceService) UpdateStatus(
	user, caller ct.UserId,
	presence *types.Presence,
	statusMessage *string,
) (types.UserStatus, types.Error) {
	if user != caller {
		return types.UserStatus{}, types.ForbiddenError("can't change the presence of other users")
	}
	status, err := s.presenceProvider.Status(user)
	if err != nil {
		return types.UserStatus{}, err
	}
	if presence != nil {
		status.Presence = *presence
	}
	if statusMessage != nil {
		status.StatusMessage = *statusMessage
	}
	_, err = s.presenceEventSink.SetUserStatus(user, status)
	if err != nil {
		return types.UserStatus{}, err
	}
	return status, nil
}
Пример #9
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())
}
Пример #10
0
func (s roomService) SetState(
	room ct.RoomId,
	caller ct.UserId,
	content types.TypedContent,
	stateKey string,
) (*types.State, types.Error) {
	userIdStateKey, parseErr := ct.ParseUserId(stateKey)
	isUserIdStateKey := parseErr == nil

	eventType := content.GetEventType()
	switch eventType {
	case types.EventTypeName:
		if stateKey != "" {
			return nil, types.ForbiddenError("state key must be empty for state " + eventType)
		}
	case types.EventTypeTopic:
		if stateKey != "" {
			return nil, types.ForbiddenError("state key must be empty for state " + eventType)
		}
	case types.EventTypeJoinRules:
		if stateKey != "" {
			return nil, types.ForbiddenError("state key must be empty for state " + eventType)
		}
	case types.EventTypePowerLevels:
		if stateKey != "" {
			return nil, types.ForbiddenError("state key must be empty for state " + eventType)
		}
	case types.EventTypeCreate:
		return nil, types.ForbiddenError("cannot set state " + eventType)

	case types.EventTypeAliases:
		return nil, types.ForbiddenError("cannot set state " + eventType)

	case types.EventTypeMembership:
		membership, ok := content.(*types.MembershipEventContent)
		if !ok || membership == nil {
			panic("expected membership event content, got " + reflect.TypeOf(content).String())
		}
		if !isUserIdStateKey {
			return nil, types.ForbiddenError("state key must be a user id for state " + eventType)
		}
		state, err := s.doMembershipChange(room, caller, userIdStateKey, membership)
		if err != nil {
			return nil, err
		}
		return state, nil
	}
	if isUserIdStateKey && userIdStateKey != caller {
		return nil, types.ForbiddenError("cannot set the state of another user")
	}

	existing, err := s.rooms.RoomState(room, eventType, stateKey)
	if err != nil {
		return nil, err
	}
	if existing != nil {
		err := s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int {
			return pl.CreateState
		})
		if err != nil {
			return nil, err
		}
	}
	err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int {
		if eventLevel, ok := pl.Events[eventType]; ok {
			return eventLevel
		}
		return pl.EventDefault
	})
	if err != nil {
		return nil, err
	}
	return s.setState(room, caller, content, stateKey)
}