summaryrefslogtreecommitdiff
path: root/misc/dashboard/godashboard/package.py
diff options
context:
space:
mode:
Diffstat (limited to 'misc/dashboard/godashboard/package.py')
-rw-r--r--misc/dashboard/godashboard/package.py128
1 files changed, 127 insertions, 1 deletions
diff --git a/misc/dashboard/godashboard/package.py b/misc/dashboard/godashboard/package.py
index 351a1fadc..6c3bd9995 100644
--- a/misc/dashboard/godashboard/package.py
+++ b/misc/dashboard/godashboard/package.py
@@ -5,12 +5,18 @@
# This is the server part of the package dashboard.
# It must be run by App Engine.
+mail_to = "adg@golang.org"
+mail_from = "Go Dashboard <adg@golang.org>"
+mail_subject = "New Project Submitted"
+
from google.appengine.api import memcache
from google.appengine.runtime import DeadlineExceededError
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
+from google.appengine.api import users
+from google.appengine.api import mail
import binascii
import datetime
import hashlib
@@ -21,6 +27,7 @@ import re
import struct
import time
import urllib2
+import sets
# Storage model for package info recorded on server.
# Just path, count, and time of last install.
@@ -30,6 +37,15 @@ class Package(db.Model):
count = db.IntegerProperty()
last_install = db.DateTimeProperty()
+class Project(db.Model):
+ name = db.StringProperty(indexed=True)
+ descr = db.StringProperty()
+ web_url = db.StringProperty()
+ package = db.ReferenceProperty(Package)
+ category = db.StringProperty(indexed=True)
+ tags = db.ListProperty(str)
+ approved = db.BooleanProperty(indexed=True)
+
re_bitbucket = re.compile(r'^bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$')
re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg)$')
re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$')
@@ -124,8 +140,118 @@ class PackagePage(webapp.RequestHandler):
self.response.set_status(500)
self.response.out.write('not ok')
+class ProjectPage(webapp.RequestHandler):
+
+ def get(self):
+ admin = users.is_current_user_admin()
+ if self.request.path == "/project/login":
+ self.redirect(users.create_login_url("/project"))
+ elif self.request.path == "/project/logout":
+ self.redirect(users.create_logout_url("/project"))
+ elif self.request.path == "/project/edit" and admin:
+ self.edit()
+ else:
+ self.list()
+
+ def post(self):
+ if self.request.path == "/project/edit":
+ self.edit(True)
+ else:
+ data = dict(map(lambda x: (x, self.request.get(x)), ["name","descr","web_url"]))
+ if reduce(lambda x, y: x or not y, data.values(), False):
+ data["submitMsg"] = "You must complete all the fields."
+ self.list(data)
+ return
+ p = Project.get_by_key_name("proj-"+data["name"])
+ if p is not None:
+ data["submitMsg"] = "A project by this name already exists."
+ self.list(data)
+ return
+ p = Project(key_name="proj-"+data["name"], **data)
+ p.put()
+
+ path = os.path.join(os.path.dirname(__file__), 'project-notify.txt')
+ mail.send_mail(
+ sender=mail_from, to=mail_to, subject=mail_subject,
+ body=template.render(path, {'project': p}))
+
+ self.list({"submitMsg": "Your project has been submitted."})
+
+ def list(self, data={}):
+ projects = Project.all().order('category').order('name')
+
+ admin = users.is_current_user_admin()
+ if not admin:
+ projects = projects.filter('approved =', True)
+
+ projects = list(projects)
+
+ tags = sets.Set()
+ for p in projects:
+ for t in p.tags:
+ tags.add(t)
+
+ tag = self.request.get("tag", None)
+ if tag:
+ projects = filter(lambda x: tag in x.tags, projects)
+
+ self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
+ path = os.path.join(os.path.dirname(__file__), 'project.html')
+ data["tag"] = tag
+ data["tags"] = tags
+ data["projects"] = projects
+ data["admin"] = admin
+ self.response.out.write(template.render(path, data))
+
+ def edit(self, save=False):
+ if save:
+ name = self.request.get("orig_name")
+ else:
+ name = self.request.get("name")
+
+ p = Project.get_by_key_name("proj-"+name)
+ if not p:
+ self.response.out.write("Couldn't find that Project.")
+ return
+
+ if save:
+ if self.request.get("do") == "Delete":
+ p.delete()
+ else:
+ pkg_name = self.request.get("package", None)
+ if pkg_name:
+ pkg = Package.get_by_key_name("pkg-"+pkg_name)
+ if pkg:
+ p.package = pkg.key()
+ for f in ['name', 'descr', 'web_url', 'category']:
+ setattr(p, f, self.request.get(f, None))
+ p.approved = self.request.get("approved") == "1"
+ p.tags = filter(lambda x: x, self.request.get("tags", "").split(","))
+ p.put()
+ self.redirect("/project")
+ return
+
+ # get all project categories and tags
+ cats, tags = sets.Set(), sets.Set()
+ for r in Project.all():
+ cats.add(r.category)
+ for t in r.tags:
+ tags.add(t)
+
+ self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
+ path = os.path.join(os.path.dirname(__file__), 'project-edit.html')
+ self.response.out.write(template.render(path, {
+ "taglist": tags, "catlist": cats, "p": p, "tags": ",".join(p.tags) }))
+
+ def redirect(self, url):
+ self.response.set_status(302)
+ self.response.headers.add_header("Location", url)
+
def main():
- app = webapp.WSGIApplication([('/package', PackagePage)], debug=True)
+ app = webapp.WSGIApplication([
+ ('/package', PackagePage),
+ ('/project.*', ProjectPage),
+ ], debug=True)
run_wsgi_app(app)
if __name__ == '__main__':