コード例 #1
0
ファイル: user.go プロジェクト: dskinner/apkbot
func userSetPassword(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	c := context.New(r)
	u := user.Current(c, db)

	if !u.Validate(r.FormValue("oldpassword")) {
		return handler.NewError(nil, 400, "Old password incorrect!")
	}

	newPass := r.FormValue("password")
	if newPass != r.FormValue("repeatpassword") {
		return handler.NewError(nil, 400, "New password doesn't match!")
	}

	if len(newPass) > 100 {
		return handler.NewError(nil, 400, "Password length over 100. Seriously?!")
	}

	u.SetPassword(newPass)
	if err := db.C("users").UpdateId(u.Id, u); err != nil {
		return handler.NewError(err, 500, "Error updating user password!")
	}

	return nil
}
コード例 #2
0
ファイル: apk.go プロジェクト: dskinner/apkbot
// download provides the requested apk by the given bson.ObjectId
func download(w http.ResponseWriter, r *http.Request) *handler.Error {
	var (
		apk Apk
		buf bytes.Buffer
	)

	db := datastore.New()
	defer db.Close()

	q := bson.M{"_id": bson.ObjectIdHex(r.FormValue("id"))}
	err := db.C("apks").Find(q).One(&apk)
	if err != nil {
		return handler.NewError(err, 404, "No record of apk.")
	}

	file, err := db.FS().OpenId(apk.FileId)
	if err != nil {
		return handler.NewError(err, 404, "No such apk.")
	}

	io.Copy(&buf, file)

	filename := fmt.Sprintf("%s-%s.apk", apk.Badging.ApplicationLabel, apk.Time)

	w.Header().Set("Content-Type", "application/vnd.android.package-archive")
	w.Header().Set("Content-Disposition", "attachment;filename="+filename)
	w.Write(buf.Bytes())

	return nil
}
コード例 #3
0
ファイル: apk.go プロジェクト: dskinner/apkbot
// icon retrieves a previously saved apk icon.
func icon(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	id := mux.Vars(r)["iconId"]

	if id == "" {
		w.Header().Set("Content-type", "image/png")
		w.Write([]byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 8, 215, 99, 96, 96, 96, 96, 0, 0, 0, 5, 0, 1, 94, 243, 42, 58, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130})
		return nil
	}

	file, err := db.FS().OpenId(bson.ObjectIdHex(id))
	if err != nil {
		return handler.NewError(err, 404, "No such icon.")
	}

	var buf bytes.Buffer
	io.Copy(&buf, file)
	// TODO set content type correctly
	w.Header().Set("Content-type", "image/png")
	w.Write(buf.Bytes())

	return nil
}
コード例 #4
0
ファイル: project.go プロジェクト: dskinner/apkbot
func ProjectById(u *user.User, id bson.ObjectId) (project *Project) {
	db := datastore.New()
	defer db.Close()

	q := bson.M{"_id": id, "userids": u.Id}
	if err := db.C("projects").Find(q).One(&project); err != nil {
		panic(err)
	}
	project.LoadLastApk(db)
	return
}
コード例 #5
0
ファイル: user.go プロジェクト: dskinner/apkbot
func userCurrent(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	c := context.New(r)
	u := user.Current(c, db)
	m := bson.M{"Name": u.Name, "Email": u.Email}

	render.Json(w, m)
	return nil
}
コード例 #6
0
ファイル: project.go プロジェクト: dskinner/apkbot
func projectsByUser(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	c := context.New(r)
	u := user.Current(c, db)

	projects := ProjectsByUser(u, db)
	render.Json(w, projects)

	return nil
}
コード例 #7
0
ファイル: project.go プロジェクト: dskinner/apkbot
func projectHistory(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	c := context.New(r)
	u := user.Current(c, db)

	id := bson.ObjectIdHex(mux.Vars(r)["projectId"])

	project := ProjectById(u, id)
	render.Json(w, project.History(db))

	return nil
}
コード例 #8
0
ファイル: apk.go プロジェクト: dskinner/apkbot
func apkById(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	apkId := bson.ObjectIdHex(mux.Vars(r)["id"])

	var apk *Apk
	// TODO confirm user has access to apk
	if err := db.C("apks").FindId(apkId).One(&apk); err != nil {
		return handler.NewError(err, 500, "Failed to locate apk.")
	}

	render.Json(w, apk)
	return nil
}
コード例 #9
0
ファイル: report.go プロジェクト: dskinner/apkbot
func errorsByApkId(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	apkId := bson.ObjectIdHex(mux.Vars(r)["apkId"])

	var reports []*Report
	q := bson.M{"apkid": apkId}
	if err := db.C("reports").Find(q).All(&reports); err != nil {
		return handler.NewError(err, 500, "Error querying for apk reports.")
	}

	render.Json(w, groupErrors(reports))
	return nil
}
コード例 #10
0
ファイル: user.go プロジェクト: dskinner/apkbot
func userSetProfile(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	c := context.New(r)
	u := user.Current(c, db)

	u.Name = r.FormValue("name")[:100]
	u.Email = r.FormValue("email")[:100]

	if err := db.C("users").UpdateId(u.Id, u); err != nil {
		return handler.NewError(err, 500, "Error updating user profile")
	}

	return nil
}
コード例 #11
0
ファイル: report.go プロジェクト: dskinner/apkbot
// report is a web handler that saves ACRA reports.
func report(w http.ResponseWriter, r *http.Request) *handler.Error {

	if err := r.ParseForm(); err != nil {
		return handler.NewError(err, 500, "Error parsing form data.")
	}

	db := datastore.New()
	defer db.Close()

	// find apk
	var apk *Apk
	name := r.FormValue("PACKAGE_NAME")
	vc := r.FormValue("APP_VERSION_CODE")
	// TODO use user submitted formid that identifies user with public hash for locating correct package
	q := bson.M{"badging.package.name": name, "badging.package.versionCode": vc}
	if err := db.C("apks").Find(q).Sort("-time").One(&apk); err != nil {
		// return 200 so acra doesn't keep resubmitting the report
		return handler.NewError(err, 200, fmt.Sprintf("No apk by given name and version code found: NAME %s VC %s", name, vc))
	}

	// save report using generic map to keep values not accounted for in Report struct.
	m := bson.M{}
	for k, v := range r.Form {
		if len(v) == 1 {
			m[k] = v[0]
		}
	}
	reportId := bson.NewObjectId()
	m["_id"] = reportId
	m["apkid"] = apk.Id
	m["time"] = time.Now()

	if err := db.C("reports").Insert(m); err != nil {
		return handler.NewError(err, 500, "Error inserting new report")
	}

	apk.ReportIds = append([]bson.ObjectId{reportId}, apk.ReportIds...)
	if err := db.C("apks").UpdateId(apk.Id, apk); err != nil {
		return handler.NewError(err, 500, "Error updating apk reportids")
	}

	// TODO send email notify if desired by user

	return nil
}
コード例 #12
0
ファイル: main.go プロジェクト: dskinner/apkbot
func main() {
	flag.Parse()

	render.Cache = *cache
	handler.Debug = *debug

	datastore.DBHost = *dbhost
	datastore.DBName = *dbname

	if *adduser != "" {
		u := user.New()
		u.Email = *adduser
		u.SetPassword("qwerty")
		db := datastore.New()
		defer db.Close()
		if err := db.C("users").Insert(u); err != nil {
			log.Fatal(err)
		}
		log.Print("user added, password is `qwerty`.")
	} else {
		if *memprofile != "" {

			c := make(chan os.Signal)
			signal.Notify(c)
			go func() {
				for sig := range c {
					log.Printf("Received %v", sig)
					f, err := os.Create(*memprofile)
					if err != nil {
						log.Fatal(err)
					}
					pprof.WriteHeapProfile(f)
					f.Close()
				}
			}()
		}
		log.Fatal(http.ListenAndServe("localhost:8090", nil))

	}
}
コード例 #13
0
ファイル: project.go プロジェクト: dskinner/apkbot
// ProjectByName finds a project for the given user by the given name
// or creates a new one if one does not exist.
func ProjectByName(u *user.User, name string) *Project {
	var projects []Project

	db := datastore.New()
	defer db.Close()

	q := bson.M{"userids": u.Id}
	if err := db.C("projects").Find(q).All(&projects); err != nil {
		panic(err)
	}

	for _, project := range projects {
		if project.PackageName == name {
			return &project
		}
	}

	// new project if one does not exist
	project := &Project{Id: bson.NewObjectId(), PackageName: name}
	project.UserIds = append(project.UserIds, u.Id)
	return project
}
コード例 #14
0
ファイル: report.go プロジェクト: dskinner/apkbot
func exportCSV(w http.ResponseWriter, r *http.Request) *handler.Error {

	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", "attachment;filename=export.csv")

	wrtr := csv.NewWriter(w)

	var sampleReport Report
	csvHeaders := listFields(sampleReport)
	wrtr.Write(csvHeaders)

	db := datastore.New()
	defer db.Close()

	var reports []*Report
	q := bson.M{"apkid": bson.ObjectIdHex(r.FormValue("id"))}
	if err := db.C("reports").Find(q).All(&reports); err != nil {
		return handler.NewError(err, 500, "Error querying for apk reports.")
	}

	for _, report := range reports {
		var record []string
		s := reflect.ValueOf(report).Elem()
		t := s.Type()
		for i := 0; i < s.NumField(); i++ {
			f := s.Field(i)
			if ignoreField(t.Field(i).Name) {
				continue
			}
			record = append(record, f.String())
		}

		wrtr.Write(record)
	}

	return nil
}
コード例 #15
0
ファイル: report.go プロジェクト: dskinner/apkbot
func errorDetails(w http.ResponseWriter, r *http.Request) *handler.Error {
	db := datastore.New()
	defer db.Close()

	// get session user
	// c := context.New(r)
	// u := user.Current(c, db)

	apkId := mux.Vars(r)["apkId"]
	reportId := mux.Vars(r)["reportId"]

	var report *Report
	db.C("reports").FindId(bson.ObjectIdHex(reportId)).One(&report)
	// get info from related reports to attach here
	var reports []*Report
	q := bson.M{"apkid": bson.ObjectIdHex(apkId)} // TODO confirm user has access to project
	if err := db.C("reports").Find(q).All(&reports); err != nil {
		return handler.NewError(err, 500, "Error querying for apk reports.")
	}
	attachGroupDetails(report, reports)

	render.Json(w, report)
	return nil
}
コード例 #16
0
ファイル: apk.go プロジェクト: dskinner/apkbot
// upload is a web handler for receiving an apk.
func upload(w http.ResponseWriter, r *http.Request) *handler.Error {

	// dont use memory for holding apk
	if err := r.ParseMultipartForm(0); err != nil {
		return handler.NewError(err, 500, "Unable to parse multipart form.")
	}

	f, _, err := r.FormFile("apk")
	if err != nil {
		return handler.NewError(err, 500, "Form file \"apk\" does not exist")
	}

	// dump badging and locate appropriate icon name within apk
	m := dumpBadging(f.(*os.File).Name())
	k := fmt.Sprintf("application-icon-%s", m["densities"].([]interface{})[0])
	res := m[k].(string)

	// locate tmp file and extract icon
	fi, err := f.(*os.File).Stat()
	if err != nil {
		return handler.NewError(err, 500, "Can't stat file.")
	}

	zr, err := zip.NewReader(f, fi.Size())
	if err != nil {
		return handler.NewError(err, 500, "Not a valid zip archive")
	}

	icon := zipReadBytes(zr, res)

	// Link current user to package name, save badging, apk file, and icon file.
	db := datastore.New()
	defer db.Close()

	u := user.Current(context.New(r), db)

	apkFile, err := db.FS().Create("")
	if err != nil {
		return handler.NewError(err, 500, "Can't save apk")
	}

	defer apkFile.Close()
	io.Copy(apkFile, f)

	iconFile, err := db.FS().Create("")
	if err != nil {
		return handler.NewError(err, 500, "Can't save icon")
	}

	defer iconFile.Close()
	iconFile.Write(icon)

	// using bson.M to store all badging values, including those not specified in struct
	apkId := bson.NewObjectId()
	apkName := m["package"].(map[string]interface{})["name"].(string)
	apkM := bson.M{
		"_id":     apkId,
		"fileid":  apkFile.Id(),
		"iconid":  iconFile.Id(),
		"time":    time.Now(),
		"badging": m,
	}

	if err = db.C("apks").Insert(apkM); err != nil {
		return handler.NewError(err, 500, "Error inserting apk info.")
	}

	project := ProjectByName(u, apkName)
	project.ApkIds = append([]bson.ObjectId{apkId}, project.ApkIds...)
	if _, err = db.C("projects").UpsertId(project.Id, project); err != nil {
		return handler.NewError(err, 500, "Error upserting project.")
	}

	http.Redirect(w, r, "/console/index", 302)
	return nil
}