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)) }
// 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 }
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)) }
// 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 }
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 } }
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 }
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 }
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)) }
// 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 }
// 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 }
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)) }
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 }