예제 #1
0
파일: core.go 프로젝트: z0rr0/luss
// HandlerTest handles test GET request.
func HandlerTest(ctx context.Context, w http.ResponseWriter, r *http.Request) ErrHandler {
	c, err := conf.FromContext(ctx)
	if err != nil {
		return ErrHandler{err, http.StatusInternalServerError}
	}
	coll, err := db.C(ctx, "tests")
	if err != nil {
		return ErrHandler{err, http.StatusInternalServerError}
	}
	command := r.FormValue("write")
	switch {
	case c.Debug && command == "add":
		err = coll.Insert(bson.M{"ts": time.Now()})
	case c.Debug && command == "del":
		err = coll.Remove(nil)
	}
	if err != nil && err != mgo.ErrNotFound {
		return ErrHandler{err, http.StatusInternalServerError}
	}
	n, err := coll.Count()
	if err != nil {
		return ErrHandler{err, http.StatusInternalServerError}
	}
	u, err := auth.ExtractUser(ctx)
	if err != nil {
		return ErrHandler{err, http.StatusInternalServerError}
	}
	c.L.Debug.Printf("user=%v", u)
	fmt.Fprintf(w, "found %v items", n)
	return ErrHandler{nil, http.StatusOK}
}
예제 #2
0
파일: api.go 프로젝트: z0rr0/luss
// HandlerInfo returns main API info.
func HandlerInfo(ctx context.Context, w http.ResponseWriter, r *http.Request) core.ErrHandler {
	c, err := conf.FromContext(ctx)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	user, err := auth.ExtractUser(ctx)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	result := &infoResponse{
		Err: 0,
		Msg: "ok",
		Result: []infoResponseItem{
			infoResponseItem{
				Version:  Version,
				AuthOk:   !user.IsAnonymous(),
				PackSize: c.Settings.MaxPack,
			},
		},
	}
	b, err := json.Marshal(result)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "%s", b)
	return core.ErrHandler{Err: nil, Status: http.StatusOK}
}
예제 #3
0
파일: trim.go 프로젝트: z0rr0/luss
// Shorten returns new short links.
func Shorten(ctx context.Context, params []*ReqParams) ([]*CustomURL, error) {
	c, err := conf.FromContext(ctx)
	if err != nil {
		return nil, err
	}
	u, err := auth.ExtractUser(ctx)
	if err != nil {
		return nil, err
	}
	// check URLs pack size
	n := len(params)
	if n > c.Settings.MaxPack {
		return nil, fmt.Errorf("too big ReqParams pack size [%v]", n)
	}
	s, err := db.CtxSession(ctx)
	if err != nil {
		return nil, err
	}
	// prepare
	coll, err := db.Coll(s, "urls")
	if err != nil {
		return nil, err
	}
	now := time.Now().UTC()
	err = db.LockURL(s)
	if err != nil {
		return nil, err
	}
	defer db.UnlockURL(s)
	num, err := getMax(coll)
	if err != nil {
		return nil, err
	}
	documents := make([]interface{}, n)
	cus := make([]*CustomURL, n)
	for i, param := range params {
		num++
		cus[i] = &CustomURL{
			ID:        num,
			Group:     param.Group,
			Tag:       param.Tag,
			Original:  param.Original,
			User:      u.Name,
			TTL:       param.TTL,
			NotDirect: param.NotDirect,
			Created:   now,
			Modified:  now,
			Cb:        param.Cb,
			API:       param.IsAPI,
		}
		documents[i] = cus[i]
	}
	err = coll.Insert(documents...)
	if err != nil {
		return nil, err
	}
	return cus, nil
}
예제 #4
0
파일: api.go 프로젝트: z0rr0/luss
// HandlerUserAdd creates new user.
func HandlerUserAdd(ctx context.Context, w http.ResponseWriter, r *http.Request) core.ErrHandler {
	var uar []userAddRequest
	user, err := auth.ExtractUser(ctx)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	if !user.HasRole("admin") {
		return core.ErrHandler{Err: errors.New("permissions error"), Status: http.StatusForbidden}
	}
	defer r.Body.Close()
	decoder := json.NewDecoder(r.Body)
	err = decoder.Decode(&uar)
	if (err != nil) && (err != io.EOF) {
		return core.ErrHandler{Err: err, Status: http.StatusBadRequest}
	}
	if len(uar) == 0 {
		return core.ErrHandler{Err: ErrEmptyRequest, Status: http.StatusNoContent}
	}
	names := make([]string, len(uar))
	for i, v := range uar {
		names[i] = v.Name
	}
	usersResult, err := auth.CreateUsers(ctx, names)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	items := make([]userAddResponseItem, len(usersResult))
	for i, ur := range usersResult {
		if ur.Err != "" {
			items[i] = userAddResponseItem{
				Name:  ur.Name,
				Token: "",
				Err:   ur.Err,
			}
		} else {
			items[i] = userAddResponseItem{
				Name:  ur.U.Name,
				Token: ur.T,
				Err:   "",
			}
		}
	}
	result := &userAddResponse{
		Err:    0,
		Msg:    "ok",
		Result: items,
	}
	b, err := json.Marshal(result)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "%s", b)
	return core.ErrHandler{Err: nil, Status: http.StatusOK}
}
예제 #5
0
파일: trim.go 프로젝트: z0rr0/luss
// Import imports short URLs.
func Import(ctx context.Context, links map[string]*ReqParams) ([]ChangeResult, error) {
	var result []ChangeResult
	c, err := conf.FromContext(ctx)
	if err != nil {
		return nil, err
	}
	u, err := auth.ExtractUser(ctx)
	if err != nil {
		return nil, err
	}
	n := len(links)
	if n > c.Settings.MaxPack {
		return nil, fmt.Errorf("too big pack size [%v]", n)
	}
	s, err := db.CtxSession(ctx)
	if err != nil {
		return nil, err
	}
	// prepare
	coll, err := db.Coll(s, "urls")
	if err != nil {
		return nil, err
	}
	now := time.Now().UTC()
	for short, param := range links {
		num, err := Decode(short)
		if err != nil {
			result = append(result, ChangeResult{Err: "invalid short URL value"})
			continue
		}
		cu := &CustomURL{
			ID:        num,
			Group:     param.Group,
			Tag:       param.Tag,
			Original:  param.Original,
			User:      u.Name,
			TTL:       param.TTL,
			NotDirect: param.NotDirect,
			Created:   now,
			Modified:  now,
			Cb:        param.Cb,
			API:       param.IsAPI,
		}
		// a locking of every insert is not fast
		// but the pack doesn't lock other operations.
		err = db.LockURL(s)
		if err != nil {
			return nil, err
		}
		errIns := coll.Insert(cu)
		err = db.UnlockURL(s)
		if err != nil {
			return nil, err
		}
		if errIns != nil {
			msg := "internal error"
			if mgo.IsDup(errIns) {
				msg = "duplicate item"
			}
			result = append(result, ChangeResult{Err: msg})
			continue
		}
		result = append(result, ChangeResult{Cu: cu})
	}
	return result, nil
}
예제 #6
0
파일: api.go 프로젝트: z0rr0/luss
// HandlerExport exports URLs data.
func HandlerExport(ctx context.Context, w http.ResponseWriter, r *http.Request) core.ErrHandler {
	const (
		layout   = "2006-01-02"
		pageSize = 1000
	)
	c, err := conf.FromContext(ctx)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	user, err := auth.ExtractUser(ctx)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	if !user.HasRole("admin") {
		return core.ErrHandler{Err: errors.New("permissions error"), Status: http.StatusForbidden}
	}
	defer r.Body.Close()

	exp := &exportRequest{}
	decoder := json.NewDecoder(r.Body)
	err = decoder.Decode(exp)
	if (err != nil) && (err != io.EOF) {
		return core.ErrHandler{Err: err, Status: http.StatusBadRequest}
	}
	period, err := exp.parsePeriod()
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	filter := trim.Filter{
		Group:    exp.Group,
		Tag:      exp.Tag,
		Period:   period,
		Active:   exp.Active,
		Page:     exp.Page,
		PageSize: pageSize,
	}
	cus, pages, err := trim.Export(ctx, filter)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	items := make([]exportResponseItem, len(cus))
	for i, cu := range cus {
		id := cu.String()
		items[i] = exportResponseItem{
			ID:       id,
			Short:    c.Address(id),
			Original: cu.Original,
			Group:    cu.Group,
			Tag:      cu.Tag,
			Created:  cu.Created.UTC().Format(layout),
		}
	}
	result := &exportResponse{
		Err:    0,
		Msg:    "ok",
		Pages:  pages,
		Result: items,
	}
	b, err := json.Marshal(result)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "%s", b)
	return core.ErrHandler{Err: nil, Status: http.StatusOK}
}
예제 #7
0
파일: api.go 프로젝트: z0rr0/luss
// HandlerImport imports predefined short URLs.
func HandlerImport(ctx context.Context, w http.ResponseWriter, r *http.Request) core.ErrHandler {
	var imprs []importRequestItem
	user, err := auth.ExtractUser(ctx)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	if !user.HasRole("admin") {
		return core.ErrHandler{Err: errors.New("permissions error"), Status: http.StatusForbidden}
	}
	defer r.Body.Close()
	decoder := json.NewDecoder(r.Body)
	err = decoder.Decode(&imprs)
	if (err != nil) && (err != io.EOF) {
		return core.ErrHandler{Err: err, Status: http.StatusBadRequest}
	}
	n := len(imprs)
	if n == 0 {
		return core.ErrHandler{Err: ErrEmptyRequest, Status: http.StatusNoContent}
	}
	links := make(map[string]*trim.ReqParams, n)
	for _, impr := range imprs {
		params := &trim.ReqParams{
			Original:  impr.Original,
			Tag:       "",
			NotDirect: false,
			IsAPI:     true,
			TTL:       nil,
			Group:     "",
			Cb:        trim.CallBack{},
		}
		err = params.Valid()
		if err != nil {
			return core.ErrHandler{Err: err, Status: http.StatusBadRequest}
		}
		links[impr.Short] = params
	}
	cus, err := trim.Import(ctx, links)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	items := make([]importResponseItem, len(cus))
	for i, cu := range cus {
		if cu.Err != "" {
			items[i] = importResponseItem{Err: cu.Err}
		} else {
			items[i] = importResponseItem{Short: cu.Cu.String()}
		}
	}
	result := &importResponse{
		Err:    0,
		Msg:    "ok",
		Result: items,
	}
	b, err := json.Marshal(result)
	if err != nil {
		return core.ErrHandler{Err: err, Status: http.StatusInternalServerError}
	}
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "%s", b)
	return core.ErrHandler{Err: nil, Status: http.StatusOK}
}