def sendVerificationMail(db, user, email_id=None): cursor = db.cursor() if email_id is None: cursor.execute("""SELECT email FROM users WHERE id=%s""", (user.id,)) email_id, = cursor.fetchone() cursor.execute("""SELECT email, verification_token FROM useremails WHERE id=%s""", (email_id,)) email, verification_token = cursor.fetchone() if verification_token is None: verification_token = auth.getToken(encode=base64.b16encode) with db.updating_cursor("useremails") as cursor: cursor.execute("""UPDATE useremails SET verification_token=%s WHERE id=%s""", (verification_token, email_id)) if configuration.base.ACCESS_SCHEME == "http": protocol = "http" else: protocol = "https" administrators = dbutils.getAdministratorContacts(db, indent=2) if administrators: administrators = ":\n\n%s" % administrators else: administrators = "." recipients = [mailutils.User(user.name, email, user.fullname)] subject = "[Critic] Please verify your email: %s" % email body = textutils.reflow(""" This is a message from the Critic code review system at %(hostname)s. The user '%(username)s' on this system has added this email address to his/her account. If this is you, please confirm this by following this link: %(url_prefix)s/verifyemail?email=%(email)s&token=%(verification_token)s If this is not you, you can safely ignore this email. If you wish to report abuse, please contact the Critic system's administrators%(administrators)s """ % { "hostname": configuration.base.HOSTNAME, "username": user.name, "email": email, "url_prefix": "%s://%s" % (protocol, configuration.base.HOSTNAME), "verification_token": verification_token, "administrators": administrators }) mailutils.sendMessage(recipients, subject, body)
def sendVerificationMail(db, user, email_id=None): cursor = db.cursor() if email_id is None: cursor.execute("""SELECT email FROM users WHERE id=%s""", (user.id,)) email_id, = cursor.fetchone() cursor.execute("""SELECT email, verification_token FROM useremails WHERE id=%s""", (email_id,)) email, verification_token = cursor.fetchone() if verification_token is None: verification_token = auth.getToken(encode=base64.b16encode) cursor.execute("""UPDATE useremails SET verification_token=%s WHERE id=%s""", (verification_token, email_id)) if configuration.base.ACCESS_SCHEME == "http": protocol = "http" else: protocol = "https" administrators = dbutils.getAdministratorContacts(db, indent=2) if administrators: administrators = ":\n\n%s" % administrators else: administrators = "." recipients = [mailutils.User(user.name, email, user.fullname)] subject = "[Critic] Please verify your email: %s" % email body = textutils.reflow(""" This is a message from the Critic code review system at %(hostname)s. The user '%(username)s' on this system has added this email address to his/her account. If this is you, please confirm this by following this link: %(url_prefix)s/verifyemail?email=%(email)s&token=%(verification_token)s If this is not you, you can safely ignore this email. If you wish to report abuse, please contact the Critic system's administrators%(administrators)s """ % { "hostname": configuration.base.HOSTNAME, "username": user.name, "email": email, "url_prefix": "%s://%s" % (protocol, configuration.base.HOSTNAME), "verification_token": verification_token, "administrators": administrators }) mailutils.sendMessage(recipients, subject, body)
def generateContent(self): table = page.utils.PaleYellowTable(self.body, "Create user") if self.provider and self.token and self.provider in auth.PROVIDERS: provider = auth.PROVIDERS[self.provider] if not provider.validateToken(self.db, self.account, self.token): raise page.utils.DisplayMessage("Invalid OAuth2 token") allow_user_registration = \ provider.configuration.get("allow_user_registration", False) else: provider = None allow_user_registration = configuration.base.ALLOW_USER_REGISTRATION if not allow_user_registration: administrators = dbutils.getAdministratorContacts( self.db, as_html=True) raise page.utils.DisplayMessage( title="User registration not enabled", body=(("<p>The administrator of this system has not enabled " "registration of new users.</p>" "<p>Contact %s if you want to use this system.</p>") % administrators), html=True) def render(target): table = target.table("createuser", align="center") def header(label): row = table.tr("header") row.td(colspan=2).text(label) def item(key): row = table.tr("item") row.td("key").text("%s:" % key) return row.td("value") def button(class_name): row = table.tr("button") return row.td(colspan=2).button(class_name) def separator(): table.tr("separator1").td(colspan=2) table.tr("separator2").td(colspan=2) if provider: self.document.addInternalScript( "var external = { provider: %s, account: %s, token: %s };" % (htmlutils.jsify(self.provider), htmlutils.jsify(self.account), htmlutils.jsify(self.token))) url = provider.getAccountURL(self.account) item(provider.getTitle()).a("external", href=url).text(self.account) separator() else: self.document.addInternalScript("var external = null;") message = table.tr("status disabled").td(colspan=2).div("message") if self.username: try: dbutils.User.fromName(self.db, self.username) except dbutils.NoSuchUser: try: auth.validateUserName(self.username) except auth.InvalidUserName as error: message.u("Invalid user name") message.br() message.text(str(error)) else: message.text("A user named '%s' already exists!" % self.username) item("New user name").input(id="newusername", value=self.username, size=40) item("Display name").input(id="fullname", value=self.fullname, size=40) item("Email").input(id="email", value=self.email, size=40) if not provider: separator() item("Password").input(id="password1", type="password", size=40) item("Password (again)").input(id="password2", type="password", size=40) button("create").text("Create user") table.addCentered(render)
def renderManageExtensions(req, db, user): if not configuration.extensions.ENABLED: administrators = dbutils.getAdministratorContacts(db, as_html=True) raise page.utils.DisplayMessage( title="Extension support not enabled", body=(("<p>This Critic system does not support extensions.</p>" "<p>Contact %s to have it enabled, or see the " "<a href='/tutorial?item=administration#extensions'>" "section on extensions</a> in the system administration " "tutorial for more information.</p>") % administrators), html=True) cursor = db.cursor() what = req.getParameter("what", "available") selected_versions = page.utils.json_decode(req.getParameter("select", "{}")) focused = req.getParameter("focus", None) if what == "installed": title = "Installed Extensions" listed_extensions = [] for extension_id, _, _, _ in Extension.getInstalls(db, user): try: listed_extensions.append(Extension.fromId(db, extension_id)) except ExtensionError as error: listed_extensions.append(error) else: title = "Available Extensions" listed_extensions = Extension.find(db) req.content_type = "text/html; charset=utf-8" document = htmlutils.Document(req) document.setTitle("Manage Extensions") html = document.html() head = html.head() body = html.body() def generateRight(target): target.a("button", href="tutorial?item=extensions").text("Tutorial") target.text(" ") target.a("button", href="tutorial?item=extensions-api").text("API Documentation") page.utils.generateHeader(body, db, user, current_page="extensions", generate_right=generateRight) document.addExternalStylesheet("resource/manageextensions.css") document.addExternalScript("resource/manageextensions.js") document.addInternalScript(user.getJS()) table = page.utils.PaleYellowTable(body, title) def addTitleRightLink(url, label): if user.name != req.user: url += "&user=%s" % user.name table.titleRight.text(" ") table.titleRight.a(href=url).text("[" + label + " extensions]") if what != "installed" or focused: addTitleRightLink("/manageextensions?what=installed", "installed") if what != "available" or focused: addTitleRightLink("/manageextensions?what=available", "available") for item in listed_extensions: if isinstance(item, ExtensionError): extension_error = item extension = item.extension else: extension_error = None extension = item if focused and extension.getKey() != focused: continue extension_path = extension.getPath() if extension.isSystemExtension(): hosting_user = None else: hosting_user = extension.getAuthor(db) selected_version = selected_versions.get(extension.getKey(), False) installed_sha1, installed_version = extension.getInstalledVersion(db, user) universal_sha1, universal_version = extension.getInstalledVersion(db, None) installed_upgradeable = universal_upgradeable = False if extension_error is None: if installed_sha1: current_sha1 = extension.getCurrentSHA1(installed_version) installed_upgradeable = installed_sha1 != current_sha1 if universal_sha1: current_sha1 = extension.getCurrentSHA1(universal_version) universal_upgradeable = universal_sha1 != current_sha1 def massage_version(version): if version is None: return "live" elif version: return "version/%s" % version else: return None if selected_version is False: selected_version = installed_version if selected_version is False: selected_version = universal_version install_version = massage_version(selected_version) installed_version = massage_version(installed_version) universal_version = massage_version(universal_version) manifest = None if extension_error is None: try: if selected_version is False: manifest = extension.getManifest() else: manifest = extension.getManifest(selected_version) except ManifestError as error: pass elif installed_sha1: manifest = extension.getManifest(installed_version, installed_sha1) elif universal_sha1: manifest = extension.getManifest(universal_version, universal_sha1) if manifest: if what == "available" and manifest.hidden: # Hide from view unless the user is hosting the extension, or is # an administrator and the extension is a system extension. if extension.isSystemExtension(): if not user.hasRole(db, "administrator"): continue elif hosting_user != user: continue else: if hosting_user != user: continue extension_id = extension.getExtensionID(db, create=False) if not user.isAnonymous(): buttons = [] if extension_id is not None: cursor.execute("""SELECT 1 FROM extensionstorage WHERE extension=%s AND uid=%s""", (extension_id, user.id)) if cursor.fetchone(): buttons.append(("Clear storage", ("clearExtensionStorage(%s, %s)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()))))) if not installed_version: if manifest and install_version and install_version != universal_version: buttons.append(("Install", ("installExtension(%s, %s, %s)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()), htmlutils.jsify(install_version))))) else: buttons.append(("Uninstall", ("uninstallExtension(%s, %s)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()))))) if manifest and (install_version != installed_version or (installed_sha1 and installed_upgradeable)): if install_version == installed_version: label = "Upgrade" else: label = "Install" buttons.append(("Upgrade", ("reinstallExtension(%s, %s, %s)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()), htmlutils.jsify(install_version))))) if user.hasRole(db, "administrator"): if not universal_version: if manifest and install_version: buttons.append(("Install (universal)", ("installExtension(%s, %s, %s, true)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()), htmlutils.jsify(install_version))))) else: buttons.append(("Uninstall (universal)", ("uninstallExtension(%s, %s, true)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()))))) if manifest and (install_version != universal_version or (universal_sha1 and universal_upgradeable)): if install_version == universal_version: label = "Upgrade (universal)" else: label = "Install (universal)" buttons.append((label, ("reinstallExtension(%s, %s, %s, true)" % (htmlutils.jsify(extension.getAuthorName()), htmlutils.jsify(extension.getName()), htmlutils.jsify(universal_version))))) else: buttons = None def renderItem(target): target.span("name").innerHTML(extension.getTitle(db, html=True)) if hosting_user: is_author = manifest and manifest.isAuthor(db, hosting_user) is_sole_author = is_author and len(manifest.authors) == 1 else: is_sole_author = False if extension_error is None: span = target.span("details") span.b().text("Details: ") select = span.select("details", critic_author=extension.getAuthorName(), critic_extension=extension.getName()) select.option(value='', selected="selected" if selected_version is False else None).text("Select version") versions = extension.getVersions() if versions: optgroup = select.optgroup(label="Official Versions") for version in versions: optgroup.option(value="version/%s" % version, selected="selected" if selected_version == version else None).text("%s" % version.upper()) optgroup = select.optgroup(label="Development") optgroup.option(value='live', selected="selected" if selected_version is None else None).text("LIVE") if manifest: is_installed = bool(installed_version) if is_installed: target.span("installed").text(" [installed]") else: is_installed = bool(universal_version) if is_installed: target.span("installed").text(" [installed (universal)]") target.div("description").preformatted().text(manifest.description, linkify=True) if not is_sole_author: authors = target.div("authors") authors.b().text("Author%s:" % ("s" if len(manifest.authors) > 1 else "")) authors.text(", ".join(author.name for author in manifest.getAuthors())) else: is_installed = False div = target.div("description broken").preformatted() if extension_error is None: anchor = div.a(href="loadmanifest?key=%s" % extension.getKey()) anchor.text("[This extension has an invalid MANIFEST file]") else: div.text("[This extension has been deleted or has become inaccessible]") if selected_version is False: return pages = [] injects = [] processcommits = [] filterhooks = [] scheduled = [] if manifest: for role in manifest.roles: if isinstance(role, PageRole): pages.append(role) elif isinstance(role, InjectRole): injects.append(role) elif isinstance(role, ProcessCommitsRole): processcommits.append(role) elif isinstance(role, FilterHookRole): filterhooks.append(role) elif isinstance(role, ScheduledRole): scheduled.append(role) role_table = target.table("roles") if pages: role_table.tr().th(colspan=2).text("Pages") for role in pages: row = role_table.tr() url = "%s/%s" % (dbutils.getURLPrefix(db, user), role.pattern) if is_installed and "*" not in url: row.td("pattern").a(href=url).text(url) else: row.td("pattern").text(url) td = row.td("description") td.text(role.description) if injects: role_table.tr().th(colspan=2).text("Page Injections") for role in injects: row = role_table.tr() row.td("pattern").text("%s/%s" % (dbutils.getURLPrefix(db, user), role.pattern)) td = row.td("description") td.text(role.description) if processcommits: role_table.tr().th(colspan=2).text("ProcessCommits hooks") ul = role_table.tr().td(colspan=2).ul() for role in processcommits: li = ul.li() li.text(role.description) if filterhooks: role_table.tr().th(colspan=2).text("FilterHook hooks") for role in filterhooks: row = role_table.tr() row.td("title").text(role.title) row.td("description").text(role.description) if scheduled: role_table.tr().th(colspan=2).text("Scheduled hooks") for role in scheduled: row = role_table.tr() row.td("pattern").text("%s @ %s" % (role.frequency, role.at)) td = row.td("description") td.text(role.description) installed_by = "" if extension_id is not None: cursor.execute("""SELECT uid FROM extensioninstalls JOIN extensions ON (extensions.id=extensioninstalls.extension) WHERE extensions.id=%s""", (extension.getExtensionID(db, create=False),)) user_ids = set(user_id for user_id, in cursor.fetchall()) if user_ids: installed_by = " (installed" if None in user_ids: installed_by += " universally" user_ids.remove(None) if user_ids: installed_by += " and" if user_ids: installed_by += (" by %d user%s" % (len(user_ids), "s" if len(user_ids) > 1 else "")) installed_by += ")" table.addItem("Extension", renderItem, extension_path + "/" + installed_by, buttons) document.addInternalScript("var selected_versions = %s;" % page.utils.json_encode(selected_versions)) return document