Пример #1
0
// URL: /admin/node/new
// 新建节点
func adminNewNodeHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin?next=/node/new", http.StatusFound)
		return
	}

	if !user.IsSuperuser {
		message(w, r, "没有权限", "你没有新建节点的权限", "error")
		return
	}

	form := wtforms.NewForm(
		wtforms.NewTextField("id", "ID", "", &wtforms.Required{}),
		wtforms.NewTextField("name", "名称", "", &wtforms.Required{}),
		wtforms.NewTextArea("description", "描述", "", &wtforms.Required{}),
	)

	if r.Method == "POST" {
		if form.Validate(r) {
			c := db.C("nodes")
			node := Node{}

			err := c.Find(bson.M{"id": form.Value("id")}).One(&node)

			if err == nil {
				form.AddError("id", "该ID已经存在")

				renderTemplate(w, r, "node/new.html", map[string]interface{}{"form": form, "adminNav": ADMIN_NAV})
				return
			}

			err = c.Find(bson.M{"name": form.Value("name")}).One(&node)

			if err == nil {
				form.AddError("name", "该名称已经存在")

				renderTemplate(w, r, "node/new.html", map[string]interface{}{"form": form, "adminNav": ADMIN_NAV})
				return
			}

			Id_ := bson.NewObjectId()
			err = c.Insert(&Node{
				Id_:         Id_,
				Id:          form.Value("id"),
				Name:        form.Value("name"),
				Description: form.Value("description")})

			if err != nil {
				panic(err)
			}

			http.Redirect(w, r, "/admin/node/new", http.StatusFound)
		}
	}

	renderTemplate(w, r, "node/new.html", map[string]interface{}{"form": form, "adminNav": ADMIN_NAV})
}
Пример #2
0
// URL: /site/new
// 提交站点
func newSiteHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin", http.StatusFound)
		return
	}

	var categories []SiteCategory
	c := db.C("sitecategories")
	c.Find(nil).All(&categories)

	var choices []wtforms.Choice

	for _, category := range categories {
		choices = append(choices, wtforms.Choice{Value: category.Id_.Hex(), Label: category.Name})
	}

	form := wtforms.NewForm(
		wtforms.NewTextField("name", "网站名称", "", wtforms.Required{}),
		wtforms.NewTextField("url", "地址", "", wtforms.Required{}, wtforms.URL{}),
		wtforms.NewTextArea("description", "描述", ""),
		wtforms.NewSelectField("category", "分类", choices, "", wtforms.Required{}),
	)

	if r.Method == "POST" {
		if !form.Validate(r) {
			renderTemplate(w, r, "site/form.html", map[string]interface{}{"form": form, "action": "/site/new", "title": "新建"})
			return
		}

		var site Site
		c = db.C("sites")
		err := c.Find(bson.M{"url": form.Value("url")}).One(&site)
		if err == nil {
			form.AddError("url", "该站点已经有了")
			renderTemplate(w, r, "site/form.html", map[string]interface{}{"form": form, "action": "/site/new", "title": "新建"})
			return
		}

		Id_ := bson.NewObjectId()

		c = db.C("sites")

		c.Insert(&Site{
			Id_:         Id_,
			Name:        form.Value("name"),
			Url:         form.Value("url"),
			Description: form.Value("description"),
			CategoryId:  bson.ObjectIdHex(form.Value("category")),
			UserId:      user.Id_,
		})

		http.Redirect(w, r, "/sites#site-"+Id_.Hex(), http.StatusFound)
		return
	}

	renderTemplate(w, r, "site/form.html", map[string]interface{}{"form": form, "action": "/site/new", "title": "新建"})
}
Пример #3
0
// URL: /package/new
// 新建第三方包
func newPackageHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin", http.StatusFound)
		return
	}

	var categories []PackageCategory

	c := db.C("packagecategories")
	c.Find(nil).All(&categories)

	var choices []wtforms.Choice

	for _, category := range categories {
		choices = append(choices, wtforms.Choice{Value: category.Id_.Hex(), Label: category.Name})
	}

	form := wtforms.NewForm(
		wtforms.NewHiddenField("html", ""),
		wtforms.NewTextField("name", "名称", "", wtforms.Required{}),
		wtforms.NewSelectField("category_id", "分类", choices, ""),
		wtforms.NewTextField("url", "网址", "", wtforms.Required{}, wtforms.URL{}),
		wtforms.NewTextArea("description", "描述", "", wtforms.Required{}),
	)

	if r.Method == "POST" && form.Validate(r) {
		c = db.C("packages")
		id := bson.NewObjectId()
		categoryId := bson.ObjectIdHex(form.Value("category_id"))
		c.Insert(&Package{
			Id_:        id,
			UserId:     user.Id_,
			CategoryId: categoryId,
			Name:       form.Value("name"),
			Url:        form.Value("url"),
			Markdown:   form.Value("description"),
			Html:       template.HTML(form.Value("html")),
			CreatedAt:  time.Now(),
		})

		c = db.C("packagecategories")
		// 增加数量
		c.Update(bson.M{"_id": categoryId}, bson.M{"$inc": bson.M{"packagecount": 1}})

		http.Redirect(w, r, "/p/"+id.Hex(), http.StatusFound)
		return
	}
	renderTemplate(w, r, "package/form.html", map[string]interface{}{"form": form, "title": "提交第三方包", "action": "/package/new"})
}
Пример #4
0
// URL: /admin/package_category/new
// 新建包分类
func adminNewPackageCategoryHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin?next=/admin/site_category/new", http.StatusFound)
		return
	}

	if !user.IsSuperuser {
		message(w, r, "没有权限", "你没有新建包分类的权限", "error")
		return
	}

	form := wtforms.NewForm(
		wtforms.NewTextField("id", "ID", "", wtforms.Required{}),
		wtforms.NewTextField("name", "名称", "", wtforms.Required{}),
	)

	if r.Method == "POST" {
		if !form.Validate(r) {
			renderTemplate(w, r, "admin/new_package_category.html", map[string]interface{}{"adminNav": ADMIN_NAV, "form": form})
			return
		}

		c := db.C("packagecategories")
		var category PackageCategory
		err := c.Find(bson.M{"name": form.Value("name")}).One(&category)

		if err == nil {
			form.AddError("name", "该名称已经有了")
			renderTemplate(w, r, "admin/new_package_category.html", map[string]interface{}{"adminNav": ADMIN_NAV, "form": form})
			return
		}

		err = c.Insert(&PackageCategory{
			Id_:  bson.NewObjectId(),
			Id:   form.Value("id"),
			Name: form.Value("name"),
		})

		if err != nil {
			panic(err)
		}

		http.Redirect(w, r, "/admin/package_category/new", http.StatusFound)
	}

	renderTemplate(w, r, "admin/new_package_category.html", map[string]interface{}{"adminNav": ADMIN_NAV, "form": form})
}
Пример #5
0
// URL: /signin
// 处理用户登录,如果登录成功,设置Cookie
func signinHandler(w http.ResponseWriter, r *http.Request) {
	next := r.FormValue("next")

	form := wtforms.NewForm(
		wtforms.NewHiddenField("next", next),
		wtforms.NewTextField("username", "用户名", "", &wtforms.Required{}),
		wtforms.NewPasswordField("password", "密码", &wtforms.Required{}),
	)

	if r.Method == "POST" {
		if form.Validate(r) {
			c := db.C("users")
			user := User{}

			err := c.Find(bson.M{"username": form.Value("username")}).One(&user)

			if err != nil {
				form.AddError("username", "该用户不存在")

				renderTemplate(w, r, "account/signin.html", map[string]interface{}{"form": form})
				return
			}

			if !user.IsActive {
				form.AddError("username", "邮箱没有经过验证,如果没有收到邮件,请联系管理员")
				renderTemplate(w, r, "account/signin.html", map[string]interface{}{"form": form})
				return
			}

			if user.Password != encryptPassword(form.Value("password")) {
				form.AddError("password", "密码和用户名不匹配")

				renderTemplate(w, r, "account/signin.html", map[string]interface{}{"form": form})
				return
			}

			session, _ := store.Get(r, "user")
			session.Values["username"] = user.Username
			session.Save(r, w)

			if form.Value("next") == "" {
				http.Redirect(w, r, "/", http.StatusFound)
			} else {
				http.Redirect(w, r, next, http.StatusFound)
			}

			return
		}
	}

	renderTemplate(w, r, "account/signin.html", map[string]interface{}{"form": form})
}
Пример #6
0
// URL /profile
// 用户设置页面,显示用户设置,用户头像,密码修改
func profileHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)

	if !ok {
		http.Redirect(w, r, "/signin?next=/profile", http.StatusFound)
		return
	}

	profileForm := wtforms.NewForm(
		wtforms.NewTextField("email", "电子邮件", user.Email, wtforms.Email{}),
		wtforms.NewTextField("website", "个人网站", user.Website),
		wtforms.NewTextField("location", "所在地", user.Location),
		wtforms.NewTextField("tagline", "签名", user.Tagline),
		wtforms.NewTextArea("bio", "个人简介", user.Bio),
	)

	if r.Method == "POST" {
		if profileForm.Validate(r) {
			c := db.C("users")
			c.Update(bson.M{"_id": user.Id_}, bson.M{"$set": bson.M{"website": profileForm.Value("website"),
				"location": profileForm.Value("location"),
				"tagline":  profileForm.Value("tagline"),
				"bio":      profileForm.Value("bio"),
			}})
			http.Redirect(w, r, "/profile", http.StatusFound)
			return
		}
	}

	changePasswordForm := wtforms.NewForm(
		wtforms.NewPasswordField("current_password", "当前密码"),
		wtforms.NewPasswordField("new_password", "新密码"),
		wtforms.NewPasswordField("confirm_password", "新密码确认"),
	)

	renderTemplate(w, r, "account/profile.html", map[string]interface{}{"user": user, "profileForm": profileForm, "changePasswordForm": changePasswordForm})
}
Пример #7
0
// URL: /forgot_password
// 忘记密码,输入用户名和邮箱,如果匹配,发出邮件
func forgotPasswordHandler(w http.ResponseWriter, r *http.Request) {
	form := wtforms.NewForm(
		wtforms.NewTextField("username", "用户名", "", wtforms.Required{}),
		wtforms.NewTextField("email", "电子邮件", "", wtforms.Email{}),
	)

	if r.Method == "POST" {
		if form.Validate(r) {
			var user User
			c := db.C("users")
			err := c.Find(bson.M{"username": form.Value("username")}).One(&user)
			if err != nil {
				form.AddError("username", "没有该用户")
			} else if user.Email != form.Value("email") {
				form.AddError("username", "用户名和邮件不匹配")
			} else {
				message2 := `Hi %s,
我们的系统收到一个请求,说你希望通过电子邮件重新设置你在 Golang中国 的密码。你可以点击下面的链接开始重设密码:

%s/reset/%s

如果这个请求不是由你发起的,那没问题,你不用担心,你可以安全地忽略这封邮件。

如果你有任何疑问,可以回复这封邮件向我提问。`
				code := uuid()
				c.Update(bson.M{"_id": user.Id_}, bson.M{"$set": bson.M{"resetcode": code}})
				message2 = fmt.Sprintf(message2, user.Username, config["host"], code)
				sendMail("[Golang中国]重设密码", message2, []string{user.Email})
				message(w, r, "通过电子邮件重设密码", "一封包含了重设密码指令的邮件已经发送到你的注册邮箱,按照邮件中的提示,即可重设你的密码。", "success")
				return
			}
		}
	}

	renderTemplate(w, r, "account/forgot_password.html", map[string]interface{}{"form": form})
}
Пример #8
0
// URL: /signup
// 处理用户注册,要求输入用户名,密码和邮箱
func signupHandler(w http.ResponseWriter, r *http.Request) {
	form := wtforms.NewForm(
		wtforms.NewTextField("username", "用户名", "", wtforms.Required{}, wtforms.Regexp{Expr: `^[a-zA-Z0-9_]{3,16}$`, Message: "请使用a-z, A-Z, 0-9以及下划线, 长度3-16之间"}),
		wtforms.NewPasswordField("password", "密码", wtforms.Required{}),
		wtforms.NewTextField("email", "电子邮件", "", wtforms.Required{}, wtforms.Email{}),
	)

	if r.Method == "POST" {
		if form.Validate(r) {
			c := db.C("users")

			result := User{}

			// 检查用户名
			err := c.Find(bson.M{"username": form.Value("username")}).One(&result)
			if err == nil {
				form.AddError("username", "该用户名已经被注册")

				renderTemplate(w, r, "account/signup.html", map[string]interface{}{"form": form})
				return
			}

			// 检查邮箱
			err = c.Find(bson.M{"email": form.Value("email")}).One(&result)

			if err == nil {
				form.AddError("email", "电子邮件地址已经被注册")

				renderTemplate(w, r, "account/signup.html", map[string]interface{}{"form": form})
				return
			}

			c2 := db.C("status")
			var status Status
			c2.Find(nil).One(&status)

			id := bson.NewObjectId()

			validateCode := uuid()
			index := status.UserIndex + 1
			err = c.Insert(&User{
				Id_:          id,
				Username:     form.Value("username"),
				Password:     encryptPassword(form.Value("password")),
				Email:        form.Value("email"),
				ValidateCode: validateCode,
				IsActive:     true,
				JoinedAt:     time.Now(),
				Index:        index,
			})

			if err != nil {
				panic(err)
			}

			c2.Update(bson.M{"_id": status.Id_}, bson.M{"$inc": bson.M{"userindex": 1}})

			// 发送邮件
			/*
							subject := "欢迎加入Golang 中国"
							message2 := `欢迎加入Golang 中国。请访问下面地址激活你的帐户。

				<a href="%s/activate/%s">%s/activate/%s</a>

				如果你没有注册,请忽略这封邮件。

				©2012 Golang 中国`
							message2 = fmt.Sprintf(message2, config["host"], validateCode, config["host"], validateCode)
							sendMail(subject, message2, []string{form.Value("email")})

							message(w, r, "注册成功", "请查看你的邮箱进行验证,如果收件箱没有,请查看垃圾邮件,如果还没有,请给[email protected]发邮件,告知你的用户名。", "success")
			*/
			message(w, r, "注册成功", fmt.Sprintf(`感谢您的注册,您已经成为Golang中国第 <strong>%d</strong>位用户,<a href="/signin">登录</a>。`, index), "success")
			return
		}
	}

	renderTemplate(w, r, "account/signup.html", map[string]interface{}{"form": form})
}
Пример #9
0
// URL: /package/{packageId}/edit
// 编辑第三方包
func editPackageHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin", http.StatusFound)
		return
	}

	vars := mux.Vars(r)
	packageId := vars["packageId"]

	package_ := Package{}
	c := db.C("packages")
	err := c.Find(bson.M{"_id": bson.ObjectIdHex(packageId)}).One(&package_)

	if err != nil {
		message(w, r, "没有该包", "没有该包", "error")
		return
	}

	if !package_.CanEdit(user.Username) {
		message(w, r, "没有权限", "你没有权限编辑该包", "error")
		return
	}

	var categories []PackageCategory

	c = db.C("packagecategories")
	c.Find(nil).All(&categories)

	var choices []wtforms.Choice

	for _, category := range categories {
		choices = append(choices, wtforms.Choice{Value: category.Id_.Hex(), Label: category.Name})
	}

	form := wtforms.NewForm(
		wtforms.NewHiddenField("html", string(package_.Html)),
		wtforms.NewTextField("name", "名称", package_.Name, wtforms.Required{}),
		wtforms.NewSelectField("category_id", "分类", choices, package_.CategoryId.Hex()),
		wtforms.NewTextField("url", "网址", package_.Url, wtforms.Required{}, wtforms.URL{}),
		wtforms.NewTextArea("description", "描述", package_.Markdown, wtforms.Required{}),
	)

	if r.Method == "POST" && form.Validate(r) {
		c = db.C("packages")
		categoryId := bson.ObjectIdHex(form.Value("category_id"))
		c.Update(bson.M{"_id": package_.Id_}, bson.M{"$set": bson.M{
			"categoryid": categoryId,
			"name":       form.Value("name"),
			"url":        form.Value("url"),
			"markdown":   form.Value("description"),
			"html":       template.HTML(form.Value("html")),
		}})

		c = db.C("packagecategories")
		if categoryId != package_.CategoryId {
			// 减少原来类别的包数量
			c.Update(bson.M{"_id": package_.CategoryId}, bson.M{"$inc": bson.M{"packagecount": -1}})
			// 增加新类别的包数量
			c.Update(bson.M{"_id": categoryId}, bson.M{"$inc": bson.M{"packagecount": 1}})
		}

		http.Redirect(w, r, "/p/"+package_.Id_.Hex(), http.StatusFound)
		return
	}
	renderTemplate(w, r, "package/form.html", map[string]interface{}{"form": form, "title": "编辑第三方包", "action": "/p/" + packageId + "/edit"})
}
Пример #10
0
// URL: /article/new
// 新建文章
func newArticleHandler(w http.ResponseWriter, r *http.Request) {
	if _, ok := currentUser(r); !ok {
		http.Redirect(w, r, "/signin", http.StatusFound)
		return
	}

	var categories []ArticleCategory
	c := db.C("articlecategories")
	c.Find(nil).All(&categories)

	var choices []wtforms.Choice

	for _, category := range categories {
		choices = append(choices, wtforms.Choice{Value: category.Id_.Hex(), Label: category.Name})
	}

	form := wtforms.NewForm(
		wtforms.NewHiddenField("html", ""),
		wtforms.NewTextField("title", "标题", "", wtforms.Required{}),
		wtforms.NewTextArea("content", "内容", "", wtforms.Required{}),
		wtforms.NewTextField("original_source", "原始出处", "", wtforms.Required{}),
		wtforms.NewTextField("original_url", "原始链接", "", wtforms.URL{}),
		wtforms.NewSelectField("category", "分类", choices, ""),
	)

	if r.Method == "POST" && form.Validate(r) {
		session, _ := store.Get(r, "user")
		username, _ := session.Values["username"]
		username = username.(string)

		user := User{}
		c = db.C("users")
		c.Find(bson.M{"username": username}).One(&user)

		c = db.C("articles")

		Id_ := bson.NewObjectId()

		html := form.Value("html")
		html = strings.Replace(html, "<pre>", `<pre class="prettyprint linenums">`, -1)

		categoryId := bson.ObjectIdHex(form.Value("category"))
		err := c.Insert(&Article{
			Id_:            Id_,
			CategoryId:     categoryId,
			UserId:         user.Id_,
			Title:          form.Value("title"),
			Markdown:       form.Value("content"),
			Html:           template.HTML(html),
			OriginalSource: form.Value("original_source"),
			OriginalUrl:    form.Value("original_url"),
			CreatedAt:      time.Now(),
		})

		if err != nil {
			panic(err)
		}

		http.Redirect(w, r, "/a/"+Id_.Hex(), http.StatusFound)
		return
	}

	renderTemplate(w, r, "article/form.html", map[string]interface{}{"form": form, "title": "新建", "action": "/article/new"})
}
Пример #11
0
// URL: /a/{articleId}/edit
// 编辑主题
func editArticleHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin", http.StatusFound)
		return
	}

	articleId := mux.Vars(r)["articleId"]

	c := db.C("articles")
	var article Article
	err := c.Find(bson.M{"_id": bson.ObjectIdHex(articleId)}).One(&article)

	if err != nil {
		message(w, r, "没有该文章", "没有该文章,不能编辑", "error")
		return
	}

	if !article.CanEdit(user.Username) {
		message(w, r, "没用该权限", "对不起,你没有权限编辑该文章", "error")
		return
	}

	var categorys []ArticleCategory
	c = db.C("articlecategories")
	c.Find(nil).All(&categorys)

	var choices []wtforms.Choice

	for _, category := range categorys {
		choices = append(choices, wtforms.Choice{Value: category.Id_.Hex(), Label: category.Name})
	}

	form := wtforms.NewForm(
		wtforms.NewHiddenField("html", ""),
		wtforms.NewTextField("title", "标题", article.Title, wtforms.Required{}),
		wtforms.NewTextArea("content", "内容", article.Markdown, wtforms.Required{}),
		wtforms.NewTextField("original_source", "原始出处", article.OriginalSource, wtforms.Required{}),
		wtforms.NewTextField("original_url", "原始链接", article.OriginalUrl, wtforms.URL{}),
		wtforms.NewSelectField("category", "分类", choices, article.CategoryId.Hex()),
	)

	content := article.Markdown
	html := article.Html

	if r.Method == "POST" {
		if form.Validate(r) {
			html := form.Value("html")
			html = strings.Replace(html, "<pre>", `<pre class="prettyprint linenums">`, -1)

			categoryId := bson.ObjectIdHex(form.Value("category"))
			c = db.C("articles")
			c.Update(bson.M{"_id": article.Id_}, bson.M{"$set": bson.M{
				"categoryid":     categoryId,
				"title":          form.Value("title"),
				"originalsource": form.Value("original_source"),
				"originalurl":    form.Value("original_url"),
				"markdown":       form.Value("content"),
				"html":           template.HTML(html),
			}})

			http.Redirect(w, r, "/a/"+article.Id_.Hex(), http.StatusFound)
			return
		}

		content = form.Value("content")
		html = template.HTML(form.Value("html"))
	}

	renderTemplate(w, r, "article/form.html", map[string]interface{}{"form": form, "title": "编辑", "action": "/a/" + articleId + "/edit", "html": html, "content": content})
}
Пример #12
0
// URL: /site/{siteId}/edit
// 修改提交过的站点信息,提交者自己或者管理员可以修改
func editSiteHandler(w http.ResponseWriter, r *http.Request) {
	user, ok := currentUser(r)
	if !ok {
		http.Redirect(w, r, "/signin", http.StatusFound)
		return
	}

	siteId := mux.Vars(r)["siteId"]

	var site Site
	c := db.C("sites")

	err := c.Find(bson.M{"_id": bson.ObjectIdHex(siteId)}).One(&site)

	if err != nil {
		message(w, r, "错误的连接", "错误的连接", "error")
		return
	}

	if !site.CanEdit(user.Username) {
		message(w, r, "没有权限", "你没有权限可以修改站点", "error")
		return
	}

	var categories []SiteCategory
	c = db.C("sitecategories")
	c.Find(nil).All(&categories)

	var choices []wtforms.Choice

	for _, category := range categories {
		choices = append(choices, wtforms.Choice{Value: category.Id_.Hex(), Label: category.Name})
	}

	form := wtforms.NewForm(
		wtforms.NewTextField("name", "网站名称", site.Name, wtforms.Required{}),
		wtforms.NewTextField("url", "地址", site.Url, wtforms.Required{}, wtforms.URL{}),
		wtforms.NewTextArea("description", "描述", site.Description),
		wtforms.NewSelectField("category", "分类", choices, site.CategoryId.Hex(), wtforms.Required{}),
	)

	if r.Method == "POST" && form.Validate(r) {
		// 检查是否用重复
		var site2 Site
		c = db.C("sites")
		err := c.Find(bson.M{"url": form.Value("url"), "_id": bson.M{"$ne": site.Id_}}).One(&site2)
		if err == nil {
			form.AddError("url", "该站点已经有了")
			renderTemplate(w, r, "site/form.html", map[string]interface{}{"form": form, "action": "/site/" + siteId + "/edit", "title": "编辑"})
			return
		}

		c.Update(bson.M{"_id": site.Id_},
			bson.M{"$set": bson.M{
				"name":        form.Value("name"),
				"url":         form.Value("url"),
				"description": form.Value("description"),
				"categoryid":  bson.ObjectIdHex(form.Value("category")),
			},
			})

		http.Redirect(w, r, "/sites#site-"+site.Id_.Hex(), http.StatusFound)
		return
	}

	renderTemplate(w, r, "site/form.html", map[string]interface{}{"form": form, "action": "/site/" + siteId + "/edit", "title": "编辑"})
}