1
0
Fork 0
mnemonics/WikiRouteService.scala.txt

320 lines
11 KiB
Plaintext

package es.amuz.tacking.service.route
import java.net.URLDecoder
import java.text.Normalizer
import java.util.UUID
import es.amuz.tacking.frame.auth.{SecurityContext, SecurityInfo}
import es.amuz.tacking.frame.jade4j.JadeContext
import es.amuz.tacking.frame.pegdown.PegDownProcessorExt
import es.amuz.tacking.frame.scalikejdbc.JDBCContext
import es.amuz.tacking.model.structured_page.{PageStatus, StructuredPageAction, StructuredPages}
import es.amuz.tacking.protocols._
import es.amuz.tacking.util.FileAndPath
import org.joda.time.DateTime
import org.pegdown.Extensions
import scalikejdbc._
import shapeless.{:: => ->:}
import spray.http.StatusCodes._
import spray.http.Uri
import spray.httpx.encoding.Gzip
import spray.routing.{Directive1, Route}
import scala.annotation.tailrec
import scala.reflect.io.Path
/**
* Created by company on 12/29/14.
*/
class WikiRouteService extends RouteService with JadeContext with SecurityContext with JDBCContext {
def queryResult(names: List[String]) = {
val matchedPages = queryPageId(names)
val matched = names.take(matchedPages.size).zip(matchedPages).map(MatchedPage.tupled)
val unmatched = names.drop(matchedPages.size)
QueryPagesRes(matched, unmatched)
}
def queryPageId(names: List[String]): List[UUID] = queryPagesId(names, None).flatten.reverse
@tailrec
private def queryPagesId(names: List[String], parentId: Option[UUID], accum: List[Option[UUID]] = Nil): List[Option[UUID]] = {
names match {
case Nil =>
accum
case tname :: rnames =>
getRequestPage(tname, parentId) match {
case None =>
accum
case pageId =>
queryPagesId(rnames, pageId, pageId :: accum)
}
}
}
def getRequestPage(urlSegment: String, parentId: Option[UUID]): Option[UUID] = {
val column = StructuredPages.column
StructuredPages.where(
sqls
.eq(column.parentId, parentId).and
.eq(column.title, urlSegment)
).apply().headOption.map(_.id)
}
def getPlaceHolder = {
val column = StructuredPages.column
StructuredPages.where(
sqls
.isNull(column.parentId).and
.eq(column.title, "PlaceHolder")
).apply().head.content
}
// todo : DeleteView에서 자식페이지를 보여준다
// annotation.tailrec
// def traverseTR[A](graph : Map[A,Set[A]], toVisit : Seq[A], visited : Set[A], accumulator : Seq[A]) : Seq[A] = {
// if(toVisit.isEmpty) {
// accumulator
// } else {
// val next = toVisit.head
// val succ = (graph(next) -- visited -- toVisit).toSeq
// // DFS :
// //traverseTR(graph, succ ++ toVisit.tail, visited + next, accumulator :+ next)
// // BFS :
// traverseTR(graph, toVisit.tail ++ succ, visited + next, accumulator :+ next)
// }
// }
//
// def traverseFrom[A](graph : Map[A,Set[A]], initial : A) =
// traverseTR(graph, Seq(initial), Set.empty, Seq.empty)
def createAction(implicit wContext: WikiPageInfo): Route =
formFields('code.as[String]) { (code) =>
complete {
log.debug("create Action!")
val name = wContext.newNameSpace.get
val parentId = wContext.exists.reverse match {
case Nil =>
None
case MatchedPage(parentName, parentId) :: acester =>
Some(parentId)
}
val column = StructuredPages.column
StructuredPages.createWithNamedValues(
column.title -> name,
column.content -> code,
column.parentId -> parentId,
column.status -> PageStatus.Show.id
)
FileAndPath.innerRedirect(wContext.uri.withQuery(), Found)
}
}
def deleteAction(implicit wContext: WikiPageInfo): Route =
withJadeContext { context =>
complete {
log.debug("delete Action!")
val keyword = wContext.trailingPath.last
context += ("title" -> s"${keyword} - Tigris")
context += ("keyword" -> keyword)
context += ("role" -> wContext.authInfo.role)
render("wiki/view", context)
}
}
def updateAction(implicit wContext: WikiPageInfo): Route =
formFields('code.as[String]) { (code) =>
complete {
val MatchedPage(pageName, pageId) = wContext.exists.last
val column = StructuredPages.column
StructuredPages.updateById(pageId.toString)
.withNamedValues(
column.content -> code,
column.modified -> Some(DateTime.now)
)
FileAndPath.innerRedirect(wContext.uri.withQuery(), Found)
}
}
def createView(implicit wContext: WikiPageInfo): Route =
withJadeContext { context =>
complete {
log.debug("create View!")
val sample = getPlaceHolder
val keyword = wContext.trailingPath.last
context += ("title" -> s"Create / ${keyword} - Tigris")
context += ("keyword" -> keyword)
context += ("content" -> sample)
context += ("role" -> wContext.authInfo.role)
render("wiki/editor", context)
}
}
def deleteView(implicit wContext: WikiPageInfo): Route =
withJadeContext { context =>
complete {
log.debug("delete View!")
val MatchedPage(pageName, pageId) = wContext.exists.last
StructuredPages.findById(pageId.toString).get
// context += ("title" -> s"${keyword} - Tigris")
// context += ("keyword" -> keyword)
render("wiki/view", context)
}
}
def updateView(implicit wContext: WikiPageInfo): Route =
withJadeContext { context =>
complete {
log.debug("update View!")
val MatchedPage(pageName, pageId) = wContext.exists.last
val pageObj = StructuredPages.findById(pageId.toString).get
val keyword = wContext.trailingPath.last
context += ("title" -> s"Update / ${keyword} - Tigris")
context += ("keyword" -> keyword)
context += ("content" -> pageObj.content)
context += ("role" -> wContext.authInfo.role)
render("wiki/editor", context)
}
}
def view(implicit wContext: WikiPageInfo): Route =
withJadeContext { context =>
complete {
log.debug("View!")
val MatchedPage(pageName, pageId) = wContext.exists.last
val pageObj = StructuredPages.findById(pageId.toString).get
val processor = new PegDownProcessorExt(Extensions.ALL)
context += ("title" -> s"${pageName} - Tigris")
context += ("keyword" -> pageName)
context += ("content" -> processor.markdownToHtml(pageObj.content))
context += ("role" -> wContext.authInfo.role)
render("wiki/view", context)
}
}
def urlsplitter(urls: List[String]): Directive1[Seq[String]] =
provide(
urls.map(URLDecoder.decode(_, "UTF-8"))
.map(Normalizer.normalize(_, Normalizer.Form.NFKC))
)
def dropSegment(orig: Uri, drop: Int): Uri = {
val parentPath = Path(orig.path.toString()).segments.dropRight(drop).mkString("/", "/", "")
orig.withPath(Uri.Path(parentPath))
}
def routeFilter(
trailingPath: Seq[String],
uri: Uri,
action: StructuredPageAction.value,
authInfo: SecurityInfo
): Directive1[(List[MatchedPage], Option[String])] =
queryResult(trailingPath.toList) match {
case QueryPagesRes(pageIdList, Nil) =>
(authInfo.userSession, action) match {
case (_, StructuredPageAction.Retrieve) =>
provide(pageIdList -> None)
case (Some(us), StructuredPageAction.Create) =>
redirect(uri.withQuery("action" -> StructuredPageAction.Update), Found)
case (Some(us), _) =>
provide(pageIdList -> None)
case (None, _) =>
requireLogin()
}
case QueryPagesRes(parentIdList, "favicon.ico" :: Nil) =>
redirect("/public/common/img/favicon.ico", SeeOther)
case QueryPagesRes(parentIdList, newName :: Nil) =>
(authInfo.userSession, action) match {
case (None, StructuredPageAction.Create) =>
requireLogin()
case (Some(us), StructuredPageAction.Create) =>
provide(parentIdList -> Some(newName))
case _ =>
redirect(
uri.withQuery("action" -> StructuredPageAction.Create), Found
)
}
case QueryPagesRes(parentIdList, newNames) =>
redirect(
dropSegment(uri, newNames.size - 1)
.withQuery("action" -> StructuredPageAction.Create),
Found)
}
def userSessionRedirector(authInfo: SecurityContext): Directive1[SecurityContext] = {
provide(authInfo)
}
def wikiRouter(implicit context: WikiPageInfo): Route =
context.action match {
case StructuredPageAction.Create =>
get(createView(context)) ~
post(createAction(context))
case StructuredPageAction.Delete =>
get(deleteView(context)) ~
post(deleteAction(context))
case StructuredPageAction.Update =>
get(updateView(context)) ~
post(updateAction(context))
case StructuredPageAction.Retrieve =>
get(view(context))
case _ =>
redirect(context.uri.copy(query = Uri.Query.Empty), SeeOther)
}
def wikiContextProvider(trailingPath: Seq[String],
uri: Uri,
action: StructuredPageAction.value,
authInfo: SecurityInfo,
exists: List[MatchedPage],
newNameSpace: Option[String]
): Directive1[WikiPageInfo] =
provide(
WikiPageInfo(trailingPath, uri, action, authInfo, exists, newNameSpace)
)
val wikiContextExtrator =
path(Segments ~ Slash.?).flatMap(urlsplitter) &
requestUri &
parameters('action.as[StructuredPageAction.value] ? StructuredPageAction.Retrieve) &
withUserSession
def wikiContextProvider(
trailingPath: Seq[String],
uri: Uri,
action: StructuredPageAction.value,
authInfo: SecurityInfo): Directive1[WikiPageInfo] = {
routeFilter(trailingPath, uri, action, authInfo).flatMap {
case (exists, newNameSpace) =>
wikiContextProvider(trailingPath, uri, action, authInfo, exists, newNameSpace)
}
}
override def receive = runRoute {
pathEndOrSingleSlash {
get {
encodeResponse(Gzip) {
withJadeContext { context =>
complete {
context += ("title" -> "Stay tuned")
render("wiki/main", context)
}
}
}
}
} ~
wikiContextExtrator {
wikiContextProvider(_, _, _, _) {
context =>
wikiRouter(context)
}
}
}
}