예제 #1
0
func serveGetEnvelopes(w http.ResponseWriter, r *http.Request) chatable.CompoundError {
	withUsername := mux.Vars(r)["username"]
	params := r.URL.Query()
	pg := params.Get("page")
	page, err := strconv.Atoi(pg)
	if err != nil || page < 1 {
		page = 1
	}

	offset := page - 1
	activeUser := auth.ActiveUser(r)
	// this should never happen
	if activeUser == nil {
		return auth.ErrUnauthenticated
	}
	withUser, err := store.UserStore.GetByUsername(withUsername)
	if err == sql.ErrNoRows {
		return chatable.NewUserError("unknown username")
	} else if err != nil {
		return chatable.NewServerError(err.Error())
	}
	envelopes, err := store.EnvelopeStore.GetByUserIDWithUserID(
		activeUser.ID, withUser.ID, offset)
	if err != nil {
		return chatable.NewServerError(err.Error())
	}
	var pubEnv []*chatable.PublicEnvelope
	for _, env := range envelopes {
		pubEnv = append(pubEnv, env.ToPublic(store.UserStore))
	}

	return writeJSON(w, chatable.NewJSONResult(pubEnv, page))
}
예제 #2
0
파일: rds.go 프로젝트: wujiang/chatable
// Enqueue pushes a PublicEnvelope into the tail of a given queue.
func (r *RdsPool) Enqueue(queue string, env chatable.PublicEnvelope) chatable.CompoundError {
	conn := r.pool.Get()
	defer conn.Close()

	bt, err := json.Marshal(env)
	if err != nil {
		return chatable.NewServerError(fmt.Sprintf("Can not marshal %+v", env))
	}
	if _, err = conn.Do("RPUSH", queue, bt); err != nil {
		return chatable.NewServerError(err.Error())
	}
	return nil
}
예제 #3
0
파일: threads.go 프로젝트: wujiang/chatable
func serveGetThreads(w http.ResponseWriter, r *http.Request) chatable.CompoundError {
	params := r.URL.Query()
	pg := params.Get("page")
	page, err := strconv.Atoi(pg)
	if err != nil || page < 1 {
		page = 1
	}

	offset := page - 1
	activeUser := auth.ActiveUser(r)
	// this should never happen
	if activeUser == nil {
		return auth.ErrUnauthenticated
	}

	threads, err := store.ThreadStore.GetByUserID(activeUser.ID, offset)
	if err != nil {
		return chatable.NewServerError(err.Error())
	}
	var pubThreads []*chatable.PublicThread
	for _, th := range threads {
		pubThreads = append(pubThreads, th.ToPublic())
	}
	return writeJSON(w, chatable.NewJSONResult(pubThreads, page))
}
예제 #4
0
파일: rds.go 프로젝트: wujiang/chatable
// Dequeue pops the first element from the given queue. This is a blocking
// operation.
func (r *RdsPool) Dequeue(queue string) (chatable.PublicEnvelope, chatable.CompoundError) {
	conn := r.pool.Get()
	defer conn.Close()

	var env chatable.PublicEnvelope
	val, err := redis.Values(conn.Do("BLPOP", queue, 0))
	if err != nil {
		return env, chatable.NewServerError(err.Error())
	}
	var q, bt []byte
	if _, err = redis.Scan(val, &q, &bt); err != nil {
		return env, chatable.NewServerError(err.Error())
	}
	if err = json.Unmarshal(bt, &env); err != nil {
		return env, chatable.NewServerError(err.Error())
	}
	return env, nil
}
예제 #5
0
파일: helper.go 프로젝트: wujiang/chatable
func writeJSON(w http.ResponseWriter, v interface{}) chatable.CompoundError {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	err := json.NewEncoder(w).Encode(v)
	if err != nil {
		return chatable.NewServerError(err.Error())
	} else {
		return nil
	}
}
예제 #6
0
파일: rds.go 프로젝트: wujiang/chatable
func (r *RdsPool) AddToQM(key string, queue string) chatable.CompoundError {
	conn := r.pool.Get()
	defer conn.Close()

	_, err := conn.Do("SADD", key, queue)
	if err != nil {
		return chatable.NewServerError(err.Error())
	}
	return nil
}
예제 #7
0
파일: rds.go 프로젝트: wujiang/chatable
func (r *RdsPool) QMMembers(key string) ([]string, chatable.CompoundError) {
	conn := r.pool.Get()
	defer conn.Close()

	val, err := redis.Strings(conn.Do("SMEMBERS", key))
	if err != nil {
		return []string{}, chatable.NewServerError(err.Error())
	}
	return val, nil
}
예제 #8
0
파일: users.go 프로젝트: wujiang/chatable
func serveCreateUser(w http.ResponseWriter, r *http.Request) chatable.CompoundError {
	if err := r.ParseForm(); err != nil {
		return chatable.NewServerError(err.Error())
	}
	valid := usersForm.Valid(r.PostForm)
	if !valid {
		return usersForm.ConsolidateErrors()
	}
	u := chatable.NewUser(usersForm.Values["first_name"].(string),
		usersForm.Values["last_name"].(string),
		usersForm.Values["username"].(string),
		usersForm.Values["password"].(string),
		usersForm.Values["email"].(string),
		usersForm.Values["phone"].(string),
		r.RemoteAddr)
	err := store.UserStore.Create(u)
	// TODO: refine the error message
	if err != nil {
		msg := err.Error()
		if strings.Contains(msg, "violates") {
			return chatable.NewUserError("Some fileds are not unique")
		}
		return chatable.NewServerError(msg)
	}
	// create a auth token
	token, err := createNewAuthToken(w, r, u)
	if err != nil {
		return chatable.NewServerError(err.Error())
	}
	data := []chatable.UserWithToken{
		chatable.UserWithToken{
			FirstName:   u.FirstName,
			LastName:    u.LastName,
			Username:    u.Username,
			Email:       u.Email,
			PhoneNumber: u.PhoneNumber,
			Token:       *token,
		},
	}
	return writeJSON(w, chatable.NewJSONResult(data, 1))
}
예제 #9
0
// createNewAuthToken creates a new auth token
func createNewAuthToken(w http.ResponseWriter, r *http.Request, u *chatable.User) (*chatable.PublicToken, chatable.CompoundError) {
	// create a new token for the user
	// client_id is on the header
	clientID := r.Header.Get("ClientID")
	cid, err := strconv.Atoi(clientID)
	if err != nil {
		cid = -1
	}
	at := chatable.NewAuthToken(u.ID, cid, chatable.StringSlice{"all"})
	if err = store.AuthTokenStore.Create(at); err != nil {
		return nil, chatable.NewServerError(err.Error())
	}
	return at.ToPublicToken(), nil
}
예제 #10
0
파일: auth.go 프로젝트: wujiang/chatable
// TokenUnAuthenticate deactivates a token.
func TokenUnAuthenticate(w http.ResponseWriter, r *http.Request) chatable.CompoundError {
	at := context.Get(r, "auth")
	if at == nil {
		return ErrUnauthenticated
	}
	authToken, ok := at.(*chatable.AuthToken)
	if !ok {
		return ErrUnauthenticated
	}
	authToken.IsActive = false
	if _, err := store.AuthTokenStore.Update(authToken); err != nil {
		return chatable.NewServerError(err.Error())
	}
	return nil
}
예제 #11
0
func serveCreateAuthToken(w http.ResponseWriter, r *http.Request) chatable.CompoundError {
	if err := r.ParseForm(); err != nil {
		return chatable.NewServerError(err.Error())
	}
	valid := authTokenForm.Valid(r.PostForm)
	if !valid {
		return authTokenForm.ConsolidateErrors()
	}
	u, err := store.UserStore.GetByUsername(authTokenForm.Values["username"].(string))
	if err != nil {
		return auth.ErrUnauthenticated
	}
	if !chatable.CompareHash(u.Password, authTokenForm.Values["password"].(string)) {
		return auth.ErrUnauthenticated
	}

	token, cerr := createNewAuthToken(w, r, u)
	if cerr != nil {
		return cerr
	}
	return writeJSON(w, chatable.NewJSONResult([]*chatable.PublicToken{token}, 1))
}
예제 #12
0
func serveWSConnect(w http.ResponseWriter, r *http.Request) chatable.CompoundError {
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		return chatable.NewServerError(err.Error())
	}
	activeUser := auth.ActiveUser(r)
	// this should never happen
	if activeUser == nil {
		return auth.ErrUnauthenticated
	}
	c := &connection{
		conn:   ws,
		uname:  activeUser.Username,
		uid:    activeUser.ID,
		outbuf: make(chan chatable.PublicEnvelope),
	}

	Hub.register <- c
	go c.write()
	c.read()

	return nil
}