mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-03 03:55:58 +01:00
(refs #10) Completed notification implementation.
This commit is contained in:
@@ -4,7 +4,7 @@ import jp.sf.amateras.scalatra.forms._
|
|||||||
|
|
||||||
import service._
|
import service._
|
||||||
import IssuesService._
|
import IssuesService._
|
||||||
import util.{CollaboratorsAuthenticator, ReferrerAuthenticator, ReadableUsersAuthenticator}
|
import util.{CollaboratorsAuthenticator, ReferrerAuthenticator, ReadableUsersAuthenticator, Notifier}
|
||||||
import org.scalatra.Ok
|
import org.scalatra.Ok
|
||||||
|
|
||||||
class IssuesController extends IssuesControllerBase
|
class IssuesController extends IssuesControllerBase
|
||||||
@@ -112,7 +112,14 @@ trait IssuesControllerBase extends ControllerBase {
|
|||||||
// record activity
|
// record activity
|
||||||
recordCreateIssueActivity(owner, name, userName, issueId, form.title)
|
recordCreateIssueActivity(owner, name, userName, issueId, form.title)
|
||||||
|
|
||||||
redirect(s"/${owner}/${name}/issues/${issueId}")
|
val uri = s"/${owner}/${name}/issues/${issueId}"
|
||||||
|
|
||||||
|
// notifications
|
||||||
|
Notifier().toNotify(repository, issueId, form.content.getOrElse("")){
|
||||||
|
Notifier.msgIssue(baseUrl + uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect(uri)
|
||||||
})
|
})
|
||||||
|
|
||||||
ajaxPost("/:owner/:repository/issues/edit/:id", issueEditForm)(readableUsersOnly { (form, repository) =>
|
ajaxPost("/:owner/:repository/issues/edit/:id", issueEditForm)(readableUsersOnly { (form, repository) =>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package servlet
|
|||||||
import javax.servlet._
|
import javax.servlet._
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import javax.servlet.http.HttpServletRequest
|
import javax.servlet.http.HttpServletRequest
|
||||||
import scala.slick.session.Database
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the transaction with the open session in view pattern.
|
* Controls the transaction with the open session in view pattern.
|
||||||
@@ -21,15 +20,19 @@ class TransactionFilter extends Filter {
|
|||||||
// assets don't need transaction
|
// assets don't need transaction
|
||||||
chain.doFilter(req, res)
|
chain.doFilter(req, res)
|
||||||
} else {
|
} else {
|
||||||
val context = req.getServletContext
|
Database(req.getServletContext) withTransaction {
|
||||||
Database.forURL(context.getInitParameter("db.url"),
|
|
||||||
context.getInitParameter("db.user"),
|
|
||||||
context.getInitParameter("db.password")) withTransaction {
|
|
||||||
logger.debug("TODO begin transaction")
|
logger.debug("TODO begin transaction")
|
||||||
chain.doFilter(req, res)
|
chain.doFilter(req, res)
|
||||||
logger.debug("TODO end transaction")
|
logger.debug("TODO end transaction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Database {
|
||||||
|
def apply(context: ServletContext): scala.slick.session.Database =
|
||||||
|
scala.slick.session.Database.forURL(context.getInitParameter("db.url"),
|
||||||
|
context.getInitParameter("db.user"),
|
||||||
|
context.getInitParameter("db.password"))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,37 +1,104 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import org.apache.commons.mail.{DefaultAuthenticator, SimpleEmail}
|
import scala.concurrent._
|
||||||
|
import ExecutionContext.Implicits.global
|
||||||
|
import org.apache.commons.mail.{DefaultAuthenticator, HtmlEmail}
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
import service.SystemSettingsService.{SystemSettings, Smtp}
|
import app.Context
|
||||||
|
import service.{AccountService, RepositoryService, IssuesService, SystemSettingsService}
|
||||||
|
import servlet.Database
|
||||||
|
import SystemSettingsService.Smtp
|
||||||
|
|
||||||
trait Notifier {
|
trait Notifier extends RepositoryService with AccountService with IssuesService {
|
||||||
|
def toNotify(r: RepositoryService.RepositoryInfo, issueId: Int, content: String)
|
||||||
|
(msg: String => String)(implicit context: Context): Unit
|
||||||
|
|
||||||
|
protected def recipients(issue: model.Issue)(notify: String => Unit)(implicit context: Context) =
|
||||||
|
(
|
||||||
|
// individual repository's owner
|
||||||
|
issue.userName ::
|
||||||
|
// collaborators
|
||||||
|
getCollaborators(issue.userName, issue.repositoryName) :::
|
||||||
|
// participants
|
||||||
|
issue.openedUserName ::
|
||||||
|
getComments(issue.userName, issue.repositoryName, issue.issueId).map(_.commentedUserName)
|
||||||
|
)
|
||||||
|
.distinct
|
||||||
|
.withFilter ( _ != context.loginAccount.get.userName ) // the operation in person is excluded
|
||||||
|
.foreach ( getAccountByUserName(_) foreach (x => notify(x.mailAddress)) )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Notifier {
|
object Notifier {
|
||||||
def apply(settings: SystemSettings) = {
|
// TODO We want to be able to switch to mock.
|
||||||
new Mailer(settings.smtp.get)
|
def apply(): Notifier = new SystemSettingsService {}.loadSystemSettings match {
|
||||||
|
case settings if settings.notification => new Mailer(settings.smtp.get)
|
||||||
|
case _ => new MockMailer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def msgIssue(url: String) = (content: String) => s"""
|
||||||
|
|${content}<br/>
|
||||||
|
|--<br/>
|
||||||
|
|<a href="${url}">View it on GitBucket</a>
|
||||||
|
""".stripMargin
|
||||||
|
|
||||||
|
def msgPullRequest(url: String) = (content: String) => s"""
|
||||||
|
|${content}<hr/>
|
||||||
|
|View, comment on, or merge it at:<br/>
|
||||||
|
|<a href="${url}">${url}</a>
|
||||||
|
""".stripMargin
|
||||||
|
|
||||||
|
def msgComment(url: String) = (content: String) => s"""
|
||||||
|
|${content}<br/>
|
||||||
|
|--<br/>
|
||||||
|
|<a href="${url}">View it on GitBucket</a>
|
||||||
|
""".stripMargin
|
||||||
|
|
||||||
|
def msgStatus(id: Int, url: String) = (content: String) => s"""
|
||||||
|
|${content} <a href="${url}">#${id}</a>
|
||||||
|
""".stripMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mailer(val smtp: Smtp) extends Notifier {
|
class Mailer(private val smtp: Smtp) extends Notifier {
|
||||||
def notifyTo(issue: model.Issue) = {
|
private val logger = LoggerFactory.getLogger(classOf[Mailer])
|
||||||
val email = new SimpleEmail
|
|
||||||
email.setHostName(smtp.host)
|
|
||||||
email.setSmtpPort(smtp.port.get)
|
|
||||||
smtp.user.foreach { user =>
|
|
||||||
email.setAuthenticator(new DefaultAuthenticator(user, smtp.password.getOrElse("")))
|
|
||||||
}
|
|
||||||
smtp.ssl.foreach { ssl =>
|
|
||||||
email.setSSLOnConnect(ssl)
|
|
||||||
}
|
|
||||||
email.setFrom("TODO address", "TODO name")
|
|
||||||
email.addTo("TODO")
|
|
||||||
email.setSubject(s"[${issue.repositoryName}] ${issue.title} (#${issue.issueId})")
|
|
||||||
email.setMsg("TODO")
|
|
||||||
|
|
||||||
email.send
|
def toNotify(r: RepositoryService.RepositoryInfo, issueId: Int, content: String)
|
||||||
|
(msg: String => String)(implicit context: Context) = {
|
||||||
|
val f = future {
|
||||||
|
val email = new HtmlEmail
|
||||||
|
email.setHostName(smtp.host)
|
||||||
|
email.setSmtpPort(smtp.port.get)
|
||||||
|
smtp.user.foreach { user =>
|
||||||
|
email.setAuthenticator(new DefaultAuthenticator(user, smtp.password.getOrElse("")))
|
||||||
|
}
|
||||||
|
smtp.ssl.foreach { ssl =>
|
||||||
|
email.setSSLOnConnect(ssl)
|
||||||
|
}
|
||||||
|
email.setFrom("notifications@gitbucket.com", context.loginAccount.get.userName)
|
||||||
|
email.setHtmlMsg(msg(view.Markdown.toHtml(content, r, false, true)))
|
||||||
|
|
||||||
|
// TODO Can we use the Database Session in other than Transaction Filter?
|
||||||
|
Database(context.request.getServletContext) withSession {
|
||||||
|
getIssue(r.owner, r.name, issueId.toString) foreach { issue =>
|
||||||
|
email.setSubject(s"[${r.name}] ${issue.title} (#${issueId})")
|
||||||
|
recipients(issue) {
|
||||||
|
email.getToAddresses.clear
|
||||||
|
email.addTo(_).send
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"Notifications Successful."
|
||||||
|
}
|
||||||
|
f onSuccess {
|
||||||
|
case s => logger.debug(s)
|
||||||
|
}
|
||||||
|
f onFailure {
|
||||||
|
case t => logger.error("Notifications Failed.", t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MockMailer extends Notifier
|
class MockMailer extends Notifier {
|
||||||
|
def toNotify(r: RepositoryService.RepositoryInfo, issueId: Int, content: String)
|
||||||
|
(msg: String => String)(implicit context: Context): Unit = {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user