Exemple #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(),
	}
}
Exemple #2
0
func (e roomsEndpoint) handlePutState(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
	room, user, err := e.getRoomAndUser(req, params)
	if err != nil {
		WriteJsonResponseWithStatus(rw, err)
		return
	}
	eventType := params[1].Value
	stateKey := ""
	if len(params) > 2 {
		stateKey = params[2].Value
	}

	var content ct.TypedContent
	switch eventType {
	case types.EventTypeMembership:
		content = &types.MembershipEventContent{}
	case types.EventTypeName:
		content = &types.NameEventContent{}
	case types.EventTypeTopic:
		content = &types.TopicEventContent{}
	case types.EventTypePowerLevels:
		content = &types.PowerLevelsEventContent{}
	case types.EventTypeJoinRules:
		content = &types.JoinRulesEventContent{}
	}
	var jsonErr error
	if content != nil {
		jsonErr = json.NewDecoder(req.Body).Decode(content)
	} else {
		genericContent := types.NewGenericContent(map[string]interface{}{}, eventType)
		content = genericContent
		jsonErr = json.NewDecoder(req.Body).Decode(&genericContent.Content)
	}
	if jsonErr != nil {
		switch err := jsonErr.(type) {
		case *json.SyntaxError:
			msg := fmt.Sprintf("error at [%d]: %s", err.Offset, err.Error())
			WriteJsonResponseWithStatus(rw, types.NotJsonError(msg))
		case *json.UnmarshalTypeError:
			msg := fmt.Sprintf("error at [%d]: expected type %s but got %s", err.Offset, err.Type, err.Value)
			WriteJsonResponseWithStatus(rw, types.BadJsonError(msg))
		default:
			WriteJsonResponseWithStatus(rw, types.BadJsonError(err.Error()))
		}
		return
	}
	state, err := e.roomService.SetState(room, user, content, stateKey)
	if err != nil {
		WriteJsonResponseWithStatus(rw, err)
		return
	}
	res := eventIdResponse{state.EventId}
	WriteJsonResponse(rw, 200, res)
}
Exemple #3
0
func (e authEndpoint) postLogin(req *http.Request, body *authRequest) interface{} {
	switch body.Type {
	case LoginTypePassword:
		hostname := strings.Split(req.Host, ":")[0]
		return e.loginWithPassword(hostname, body)
	}
	return types.BadJsonError(fmt.Sprintf("Missing or invalid login type: '%s'", body.Type))
}
Exemple #4
0
func (e eventsEndpoint) getSingleEvent(req *http.Request, params httprouter.Params) interface{} {
	authedUser, err := readAccessToken(e.userService, e.tokenService, req)
	if err != nil {
		return err
	}
	eventId, parseErr := ct.ParseEventId(params[0].Value)
	if parseErr != nil {
		return types.BadJsonError(parseErr.Error())
	}
	event, err := e.eventService.Event(authedUser, eventId)
	if err != nil {
		return err
	}
	return event
}
Exemple #5
0
func (e profileEndpoint) setAvatarUrl(req *http.Request, params httprouter.Params, body *avatarUrlRequest) interface{} {
	authedUser, err := readAccessToken(e.users, e.tokens, req)
	if err != nil {
		return err
	}
	user, err := urlParams{params}.user(0, e.users)
	if err != nil {
		return err
	}
	if body.AvatarUrl == nil {
		return types.BadJsonError("missing 'avatar_url'")
	}
	if _, err := e.profiles.UpdateProfile(user, authedUser, nil, body.AvatarUrl); err != nil {
		return err
	}
	return struct{}{}
}
Exemple #6
0
func (e profileEndpoint) setDisplayName(req *http.Request, params httprouter.Params, body *displayNameRequest) interface{} {
	authedUser, err := readAccessToken(e.users, e.tokens, req)
	if err != nil {
		return err
	}
	user, err := urlParams{params}.user(0, e.users)
	if err != nil {
		return err
	}
	if body.DisplayName == nil {
		return types.BadJsonError("missing 'displayname'")
	}
	if _, err := e.profiles.UpdateProfile(user, authedUser, body.DisplayName, nil); err != nil {
		return err
	}
	return struct{}{}
}
Exemple #7
0
func (e presenceEndpoint) setStatus(req *http.Request, params httprouter.Params, body *statusRequest) interface{} {
	authedUser, err := readAccessToken(e.users, e.tokens, req)
	if err != nil {
		return err
	}
	user, err := urlParams{params}.user(0, e.users)
	if err != nil {
		return err
	}
	if body.Presence == nil && body.StatusMessage == nil {
		return types.BadJsonError("empty request")
	}
	_, err = e.presences.UpdateStatus(user, authedUser, body.Presence, body.StatusMessage)
	if err != nil {
		return err
	}
	return struct{}{}
}
Exemple #8
0
func (e authEndpoint) registerWithPassword(hostname string, body *authRequest) interface{} {
	if body.Username == "" {
		body.Username = utils.RandomString(24)
	}
	if body.Password == "" {
		return types.BadJsonError("Missing or invalid password")
	}
	userId := ct.NewUserId(body.Username, hostname)
	err := e.userService.CreateUser(userId)
	if err != nil {
		return err
	}
	if err := e.userService.SetPassword(userId, userId, body.Password); err != nil {
		return err
	}
	accessToken, err := e.tokenService.NewAccessToken(userId)
	if err != nil {
		return err
	}
	return authResponse{
		UserId:      userId,
		AccessToken: accessToken.String(),
	}
}
Exemple #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())
}
Exemple #10
0
func jsonHandler(i interface{}) httprouter.Handle {
	t := reflect.TypeOf(i)
	if reflect.Func != t.Kind() {
		panic("jsonHandler: must be a function")
	}
	if t.NumOut() != 1 {
		panic("jsonHandler: must return a single value")
	}
	argCount := t.NumIn()

	var jsonType reflect.Type
	firstParamIsParams := false
	if argCount > 0 {
		firstParamIsParams = t.In(0).String() == "httprouter.Params"
		lastParamIsParams := t.In(argCount-1).String() == "httprouter.Params"
		lastParamIsRequest := t.In(argCount-1).String() == "*http.Request"
		if !lastParamIsParams && !lastParamIsRequest {
			typ := t.In(argCount - 1)
			if typ.Kind() != reflect.Ptr {
				panic("jsonHandler: body argument must be a pointer type, was " + typ.String())
			}
			jsonType = typ.Elem()
		}
	}
	if jsonType == nil {
		if t.NumIn() > 2 {
			panic("jsonHandler: arity must be at most 2 if no body argument is preset")
		}
	} else {
		if t.NumIn() > 3 {
			panic("jsonHandler: arity must be at most 3 if body argument is preset")
		}
	}
	handlerFunc := reflect.ValueOf(i)

	return func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
		var returnValue reflect.Value
		var args []reflect.Value
		if jsonType == nil {
			switch argCount {
			case 0:
				args = []reflect.Value{}
			case 1:
				if firstParamIsParams {
					args = []reflect.Value{reflect.ValueOf(params)}
				} else {
					args = []reflect.Value{reflect.ValueOf(req)}
				}
			case 2:
				if firstParamIsParams {
					args = []reflect.Value{reflect.ValueOf(params), reflect.ValueOf(req)}
				} else {
					args = []reflect.Value{reflect.ValueOf(req), reflect.ValueOf(params)}
				}
			}
		} else {
			body := reflect.New(jsonType)
			if err := json.NewDecoder(req.Body).Decode(body.Interface()); err != nil {
				switch err := err.(type) {
				case *json.SyntaxError:
					msg := fmt.Sprintf("error at [%d]: %s", err.Offset, err.Error())
					WriteJsonResponseWithStatus(rw, types.NotJsonError(msg))
				case *json.UnmarshalTypeError:
					msg := fmt.Sprintf("error at [%d]: expected type %s but got %s", err.Offset, err.Type, err.Value)
					WriteJsonResponseWithStatus(rw, types.BadJsonError(msg))
				default:
					WriteJsonResponseWithStatus(rw, types.BadJsonError(err.Error()))
				}
				return
			}
			switch argCount {
			case 1:
				args = []reflect.Value{body}
			case 2:
				if firstParamIsParams {
					args = []reflect.Value{reflect.ValueOf(params), body}
				} else {
					args = []reflect.Value{reflect.ValueOf(req), body}
				}
			case 3:
				if firstParamIsParams {
					args = []reflect.Value{reflect.ValueOf(params), reflect.ValueOf(req), body}
				} else {
					args = []reflect.Value{reflect.ValueOf(req), reflect.ValueOf(params), body}
				}
			}
		}
		returnValue = handlerFunc.Call(args)[0]
		res := returnValue.Interface()

		withStatus, ok := res.(WithStatus)
		if ok {
			WriteJsonResponseWithStatus(rw, withStatus)
		} else {
			WriteJsonResponse(rw, 200, res)
		}
	}
}