Skip to content

Commit

Permalink
Merge branch 'release/0.3.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
lnds committed Jul 23, 2017
2 parents 4c82e13 + cd0c41f commit d9f7e20
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 166 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@

## [Unreleased]

## 0.3.3
## 0.3.4 - 2017-07-23

### Fixed
- codacy code smells
- reduces complexity of function formatElapsed on PostAux

### Changed
- refactor of PostsController

### Added
- message for unpublished post on messages i18n

## 0.3.3 - 2017-07-22

### Fixed
- codacy security warning on ImagesController and ContentManager
Expand Down
10 changes: 6 additions & 4 deletions app/controllers/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,24 @@ import jp.t2v.lab.play2.auth.OptionalAuthElement
import models.{AuthorsDAO, Guest, PostsDAO}
import play.api.db.slick.DatabaseConfigProvider
import play.api.i18n.{I18nSupport, MessagesApi}
import play.api.mvc.Controller
import play.api.mvc.{Action, AnyContent, Controller}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

class Application @Inject()(val messagesApi:MessagesApi, dbConfigProvider:DatabaseConfigProvider, val postsDAO:PostsDAO, override protected val authorsDAO:AuthorsDAO) extends Controller with OptionalAuthElement with AuthConfigImpl with I18nSupport {
class Application @Inject()(val messagesApi:MessagesApi, dbConfigProvider:DatabaseConfigProvider,
val postsDAO:PostsDAO, override protected val authorsDAO:AuthorsDAO)
extends Controller with OptionalAuthElement with AuthConfigImpl with I18nSupport {

val maxPosts = 10

def index = AsyncStack { implicit request =>
def index: Action[AnyContent] = AsyncStack { implicit request =>
postsDAO.last(maxPosts).map { posts =>
Ok(views.html.index("Prosa", posts, loggedIn.getOrElse(Guest)))
}
}

def untrail(path: String) = AsyncStack { implicit request =>
def untrail(path: String): Action[AnyContent] = AsyncStack { implicit request =>
Future.successful(MovedPermanently("/" + path))
}

Expand Down
20 changes: 10 additions & 10 deletions app/controllers/AuthConfigImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,30 @@ trait AuthConfigImpl extends AuthConfig {
type User = Author
type Authority = Permission

val idTag : ClassTag[Id] = classTag[Id]
val idTag: ClassTag[Id] = classTag[Id]

val sessionTimeoutInSeconds = 3600

protected val authorsDAO : AuthorsDAO
protected val authorsDAO: AuthorsDAO

def resolveUser(id:Id)(implicit ctx:ExecutionContext) : Future[Option[User]] =
authorsDAO.findById(id)
def resolveUser(id: Id)(implicit ctx: ExecutionContext): Future[Option[User]] =
authorsDAO.findById(id)

def loginSucceeded(request:RequestHeader)(implicit ctx:ExecutionContext) : Future[Result] = {
def loginSucceeded(request: RequestHeader)(implicit ctx: ExecutionContext): Future[Result] = {
val uri = request.session.get("access_uri").getOrElse(routes.BlogsGuestController.index().url.toString)
Future.successful(Redirect(uri).withSession(request.session - "access_uri"))
}

def logoutSucceeded(request:RequestHeader)(implicit ctx:ExecutionContext) = Future.successful(Redirect(routes.Application.index()))
def logoutSucceeded(request: RequestHeader)(implicit ctx: ExecutionContext): Future[Result] = Future.successful(Redirect(routes.Application.index()))

def authenticationFailed(request:RequestHeader)(implicit ctx:ExecutionContext) : Future[Result] =
def authenticationFailed(request: RequestHeader)(implicit ctx: ExecutionContext): Future[Result] =
Future.successful(Redirect(routes.AuthController.login()).withSession("access_uri" -> request.uri))

override def authorizationFailed(request:RequestHeader, user: User, authority: Option[Authority])(implicit ctx:ExecutionContext) = {
override def authorizationFailed(request: RequestHeader, user: User, authority: Option[Authority])(implicit ctx: ExecutionContext): Future[Result] = {
Future(Redirect(routes.AuthController.login()))
}

def authorize(user:User, authority:Authority)(implicit ctx:ExecutionContext) = Future.successful((Permission.valueOf(user.permission), authority) match {
def authorize(user: User, authority: Authority)(implicit ctx: ExecutionContext): Future[Boolean] = Future.successful((Permission.valueOf(user.permission), authority) match {
case (Administrator, _) => true
case (Editor, Editor) => true
case (Editor, Writer) => true
Expand All @@ -47,6 +47,6 @@ trait AuthConfigImpl extends AuthConfig {

override lazy val tokenAccessor = new CookieTokenAccessor(
cookieSecureOption = false,
cookieMaxAge = Some(sessionTimeoutInSeconds)
cookieMaxAge = Some(sessionTimeoutInSeconds)
)
}
3 changes: 2 additions & 1 deletion app/controllers/ImagesController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import tools.ContentManager



class ImagesController @Inject()(val messagesApi: MessagesApi, dbConfigProvider: DatabaseConfigProvider, private val contentManager: ContentManager, private val imagesDAO: ImagesDAO, protected val authorsDAO:AuthorsDAO)
class ImagesController @Inject()(val messagesApi: MessagesApi, dbConfigProvider: DatabaseConfigProvider, private val contentManager: ContentManager,
private val imagesDAO: ImagesDAO, protected val authorsDAO:AuthorsDAO)
extends Controller with AuthElement with AuthConfigImpl with I18nSupport {

val createForm = Form(
Expand Down
161 changes: 60 additions & 101 deletions app/controllers/PostsController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,43 @@ import models._
import play.api.data.Form
import play.api.data.Forms._
import play.api.db.slick.DatabaseConfigProvider
import play.api.i18n.{I18nSupport, Messages, MessagesApi}
import play.api.mvc.Controller
import play.api.i18n.{Messages, MessagesApi}
import play.api.mvc.{Action, AnyContent, Controller, Result}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scalaz._
import Scalaz._
import tools.PostAux


case class PostData(image:Option[String], title:String, subtitle:Option[String], content:String, draft:Boolean, publish:Option[Boolean])

class PostsController @Inject() (val messagesApi: MessagesApi, dbConfigProvider: DatabaseConfigProvider, val postsDAO: PostsDAO, blogsDAO: BlogsDAO, override protected val authorsDAO:AuthorsDAO) extends Controller with TokenValidateElement with AuthElement with AuthConfigImpl with I18nSupport {

val blogNotFound = Redirect(routes.BlogsGuestController.index()).flashing("error" -> Messages("blogs.error.not_found"))

def postNotFound(alias:String) = Redirect(routes.PostsGuestController.index(alias)).flashing("error" -> Messages("posts.error.not_found"))

val indexView = views.html.post_index

class PostsController @Inject() (val messagesApi: MessagesApi, dbConfigProvider: DatabaseConfigProvider, val postsDAO: PostsDAO, blogsDAO: BlogsDAO, override protected val authorsDAO:AuthorsDAO)
extends WithPostController with TokenValidateElement with AuthElement with AuthConfigImpl {


def index(alias:String, pageNum:Int=0) = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
authorsDAO.findById(blog.owner).flatMap { author =>
authorsDAO.avatar(blog.owner).flatMap { avatar =>
postsDAO.listForBlog(blog, draft = false, page = pageNum).map { list =>
Ok(indexView(blog, author, list, drafts = false, loggedIn, avatar))
}
def index(alias: String, pageNum: Int = 0): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
withBlog(blogsDAO, alias) { blog =>
authorsDAO.findById(blog.owner).flatMap { author =>
authorsDAO.avatar(blog.owner).flatMap { avatar =>
postsDAO.listForBlog(blog, draft = false, page = pageNum).map { list =>
Ok(indexView(blog, author, list, drafts = false, loggedIn, avatar))
}
}
}
}
}

def drafts(alias:String, pageNum:Int=0) = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
authorsDAO.findById(blog.owner).flatMap { author =>
postsDAO.listForBlog(blog, draft = true, page = pageNum).map { list =>
Ok(indexView(blog, author, list, drafts = true, loggedIn, PostAux.avatarUrl(loggedIn.email)))
}
def drafts(alias: String, pageNum: Int = 0): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
withBlog(blogsDAO, alias) { blog =>
authorsDAO.findById(blog.owner).flatMap { author =>
postsDAO.listForBlog(blog, draft = true, page = pageNum).map { list =>
Ok(indexView(blog, author, list, drafts = true, loggedIn, PostAux.avatarUrl(loggedIn.email)))
}
}
}
}


val postForm = Form(
mapping (
mapping(
"image" -> optional(text),
"title" -> nonEmptyText,
"subtitle" -> optional(text),
Expand All @@ -66,90 +53,62 @@ class PostsController @Inject() (val messagesApi: MessagesApi, dbConfigProvider
)(PostData.apply)(PostData.unapply)
)

def create(alias:String) = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
blogsDAO.findByAlias(alias).map {
case None => blogNotFound
case Some(blog) =>
Ok(views.html.posts_new(blog, postForm, loggedIn))
def create(alias: String): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
withBlog(blogsDAO, alias) { blog =>
Future.successful(Ok(views.html.posts_new(blog, postForm, loggedIn)))
}
}

def save(alias:String) = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
postForm.bindFromRequest.fold(
formWithErrors => Future.successful(BadRequest(views.html.posts_new(blog, formWithErrors, loggedIn))),
postData => {
postsDAO.create(loggedIn, blog, postData.title, postData.subtitle, postData.content, postData.draft, postData.image).map { post =>
if (post.draft)
Redirect(routes.PostsController.drafts(blog.alias)).flashing("success" -> Messages("posts.success.created"))
else
Redirect(routes.PostsGuestController.index(alias)).flashing("success" -> Messages("posts.success.created"))
}
})
def save(alias: String): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
withBlog(blogsDAO, alias) { blog =>
postForm.bindFromRequest.fold(
formWithErrors => Future.successful(BadRequest(views.html.posts_new(blog, formWithErrors, loggedIn))),
postData => {
postsDAO.create(loggedIn, blog, postData.title, postData.subtitle, postData.content, postData.draft, postData.image).map { post =>
if (post.draft)
Redirect(routes.PostsController.drafts(blog.alias)).flashing("success" -> Messages("posts.success.created"))
else
Redirect(routes.PostsGuestController.index(alias)).flashing("success" -> Messages("posts.success.created"))
}
})
}
}

def edit(alias:String, id:String) = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
postsDAO.findById(id).map {
case None => blogNotFound
case Some(post) =>
if (post.author === loggedIn.id)
Ok(views.html.posts_edit(blog, post, postForm.fill(PostData(post.image, post.title, post.subtitle, post.content, post.draft, Some(post.published.isDefined))), loggedIn))
else
postNotFound(alias)
}
def edit(alias: String, id: String): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer, IgnoreTokenValidation -> None) { implicit request =>
withPost(blogsDAO, postsDAO, alias, id) { (blog, post) =>
if (post.author == loggedIn.id)
Ok(views.html.posts_edit(blog, post, postForm.fill(PostData(post.image, post.title, post.subtitle, post.content, post.draft, Some(post.published.isDefined))), loggedIn))
else
postNotFound(alias)
}
}

def update(alias:String, id:String) = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
postsDAO.findById(id).map {
case None => postNotFound(alias)
case Some(post) =>
postForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.posts_new(blog, formWithErrors, loggedIn)),
postData => {
postsDAO.update(post, postData.title, postData.subtitle, postData.content, postData.draft, postData.image, postData.publish.getOrElse(false))
Redirect(routes.PostsController.edit(alias, id)).flashing("success" -> Messages("posts.success.saved"))
}
)
def update(alias: String, id: String): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
withPost(blogsDAO, postsDAO, alias, id) { (blog, post) =>
postForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.posts_new(blog, formWithErrors, loggedIn)),
postData => {
postsDAO.update(post, postData.title, postData.subtitle, postData.content, postData.draft, postData.image, postData.publish.getOrElse(false))
Redirect(routes.PostsController.edit(alias, id)).flashing("success" -> Messages("posts.success.saved"))
}
)
}
}

def delete(alias:String, id:String) = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
postsDAO.findById(id).map {
case None => postNotFound(alias)
case Some(post) =>
postsDAO.delete(post.id)
if (post.draft)
Redirect(routes.PostsController.drafts(alias)).flashing("success" -> Messages("posts.success.deleted"))
else
Redirect(routes.PostsGuestController.index(alias)).flashing("success" -> Messages("posts.success.deleted"))
}
}
def delete(alias: String, id: String): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
withPost(blogsDAO, postsDAO, alias, id) { (_, post) =>
postsDAO.delete(post.id)
if (post.draft)
Redirect(routes.PostsController.drafts(alias)).flashing("success" -> Messages("posts.success.deleted"))
else
Redirect(routes.PostsGuestController.index(alias)).flashing("success" -> Messages("posts.success.deleted"))
}
}

def unpublish(alias:String, id:String) = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
postsDAO.findById(id).map {
case None => postNotFound(alias)
case Some(post) =>
postsDAO.update(post.copy(draft = true, published = None))
Redirect(routes.PostsController.edit(alias, id)).flashing("success" -> Messages("posts.success.unpublished"))
}
def unpublish(alias: String, id: String): Action[AnyContent] = AsyncStack(AuthorityKey -> models.Writer) { implicit request =>
withPost(blogsDAO, postsDAO, alias, id) { (_, post) =>
postsDAO.update(post.copy(draft = true, published = None))
Redirect(routes.PostsController.edit(alias, id)).flashing("success" -> Messages("posts.success.unpublished"))
}
}

Expand Down
28 changes: 12 additions & 16 deletions app/controllers/PostsGuestController.scala
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
package controllers

import javax.inject.Inject

import jp.t2v.lab.play2.auth.OptionalAuthElement
import models._
import play.api.db.slick.DatabaseConfigProvider
import play.api.i18n.{MessagesApi, I18nSupport, Messages}
import play.api.mvc.Controller
import play.api.i18n.{I18nSupport, MessagesApi}
import play.api.mvc.{Action, AnyContent}
import tools.PostAux

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

class PostsGuestController @Inject() (val messagesApi: MessagesApi, dbConfigProvider: DatabaseConfigProvider, val blogsDAO: BlogsDAO, val postsDAO: PostsDAO, override protected val authorsDAO:AuthorsDAO)
extends Controller with OptionalAuthElement with AuthConfigImpl with I18nSupport {

val blogNotFound = Redirect(routes.BlogsGuestController.index())
.flashing("error" -> Messages("blogs.error.not_found"))

def postNotFound(alias:String) = Redirect(routes.PostsGuestController.index(alias))
.flashing("error" -> Messages("posts.error.not_found"))

val indexView = views.html.post_index
class PostsGuestController @Inject() (val messagesApi: MessagesApi, dbConfigProvider: DatabaseConfigProvider,
val blogsDAO: BlogsDAO, val postsDAO: PostsDAO, override protected val authorsDAO:AuthorsDAO)
extends WithPostController with OptionalAuthElement with AuthConfigImpl with I18nSupport {

def index(alias:String, pageNum:Int=0) = AsyncStack { implicit request =>
def index(alias:String, pageNum:Int=0): Action[AnyContent] = AsyncStack { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
Expand All @@ -34,7 +30,7 @@ class PostsGuestController @Inject() (val messagesApi: MessagesApi, dbConfigProv
}
}

def view(alias:String, year:Int, month:Int, day:Int, slug:String) = AsyncStack {
def view(alias:String, year:Int, month:Int, day:Int, slug:String): Action[AnyContent] = AsyncStack {
implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
Expand All @@ -50,11 +46,11 @@ class PostsGuestController @Inject() (val messagesApi: MessagesApi, dbConfigProv
}


def atom(alias:String) = AsyncStack { implicit request =>
def atom(alias:String): Action[AnyContent] = AsyncStack { implicit request =>
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
postsDAO.last(blog, 10).map { list =>
postsDAO.last(blog, PostAux.defaultPageSize).map { list =>
Ok(views.xml.posts_atom(blog, list))
}
}
Expand Down
24 changes: 24 additions & 0 deletions app/controllers/WithBlogController.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package controllers

import models.{Blog, BlogsDAO}
import play.api.i18n.{I18nSupport, Messages}
import play.api.mvc.{Controller, Result, Results}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future


/**
* Created by ediaz on 7/23/17.
*/
trait WithBlogController extends Controller with I18nSupport {

val blogNotFound: Result = Redirect(routes.BlogsGuestController.index()).flashing("error" -> Messages("blogs.error.not_found"))

def withBlog(blogsDAO: BlogsDAO, alias: String)(f: Blog => Future[Result]): Future[Result] =
blogsDAO.findByAlias(alias).flatMap {
case None => Future.successful(blogNotFound)
case Some(blog) =>
f(blog)
}
}
Loading

0 comments on commit d9f7e20

Please sign in to comment.