Skip to content

Commit

Permalink
Fix some security vulnerabilities
Browse files Browse the repository at this point in the history
Note: This will probably break some API actions for now

Signed-off-by: Walker Crouse <walkercrouse@hotmail.com>
  • Loading branch information
windy1 committed Jan 3, 2017
1 parent 0cddaff commit aa8d753
Show file tree
Hide file tree
Showing 27 changed files with 256 additions and 110 deletions.
6 changes: 6 additions & 0 deletions app/Filters.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import javax.inject.Inject

import play.api.http.DefaultHttpFilters
import play.filters.csrf.CSRFFilter

class Filters @Inject()(csrfFilters: CSRFFilter) extends DefaultHttpFilters(csrfFilters)
10 changes: 10 additions & 0 deletions app/assets/stylesheets/_project.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@
margin-bottom: 10px;
}

.form-channel-delete {
margin: 0;
display: inline;
}

.form-inline {
margin: 0;
display: inline;
}

.version-header {
position: relative;
margin-top: 0;
Expand Down
41 changes: 23 additions & 18 deletions app/controllers/Organizations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,30 @@ class Organizations @Inject()(forms: OreForms,
* @return Redirect to organization page
*/
def create() = UserLock() { implicit request =>
val user = request.user
val failCall = routes.Organizations.showCreator()
if (user.ownedOrganizations.size >= this.createLimit)
BadRequest
else if (user.isLocked)
Redirect(failCall).withError("error.user.locked")
else {
this.forms.OrganizationCreate.bindFromRequest().fold(
hasErrors =>
FormError(failCall, hasErrors),
formData => {
this.organizations.create(formData.name, user.id.get, formData.build()) match {
case Left(error) =>
Redirect(failCall).withError(error)
case Right(organization) =>
Redirect(routes.Users.showProjects(organization.name, None))
if (true) {
Redirect(routes.Application.showHome(None, None, None, None, None))
.withError("Creation of new Organizations is temporarily disabled.")
} else {
val user = request.user
val failCall = routes.Organizations.showCreator()
if (user.ownedOrganizations.size >= this.createLimit)
BadRequest
else if (user.isLocked)
Redirect(failCall).withError("error.user.locked")
else {
this.forms.OrganizationCreate.bindFromRequest().fold(
hasErrors =>
FormError(failCall, hasErrors),
formData => {
this.organizations.create(formData.name, user.id.get, formData.build()) match {
case Left(error) =>
Redirect(failCall).withError(error)
case Right(organization) =>
Redirect(routes.Users.showProjects(organization.name, None))
}
}
}
)
)
}
}
}

Expand Down
20 changes: 16 additions & 4 deletions app/controllers/project/Projects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,14 @@ class Projects @Inject()(stats: StatTracker,
case None =>
Redirect(self.showCreator())
case Some(pendingProject) =>
pendingProject.settings.save(pendingProject.underlying, this.forms.ProjectSave.bindFromRequest().get)
Ok(views.invite(pendingProject))
this.forms.ProjectSave.bindFromRequest().fold(
hasErrors =>
FormError(self.showCreator(), hasErrors),
formData => {
pendingProject.settings.save(pendingProject.underlying, formData)
Ok(views.invite(pendingProject))
}
)
}
}

Expand Down Expand Up @@ -418,8 +424,14 @@ class Projects @Inject()(stats: StatTracker,
*/
def save(author: String, slug: String) = SettingsEditAction(author, slug) { implicit request =>
val project = request.project
project.settings.save(project, this.forms.ProjectSave.bindFromRequest().get)
Redirect(self.show(author, slug))
this.forms.ProjectSave.bindFromRequest().fold(
hasErrors =>
FormError(self.showSettings(author, slug), hasErrors),
formData => {
project.settings.save(project, formData)
Redirect(self.show(author, slug))
}
)
}

/**
Expand Down
23 changes: 19 additions & 4 deletions app/form/OreForms.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package form

import java.net.{MalformedURLException, URL}
import javax.inject.Inject

import form.organization.{OrganizationAvatarUpdate, OrganizationMembersUpdate, OrganizationRoleSetBuilder}
Expand All @@ -18,6 +19,20 @@ import play.api.data.Forms._
//noinspection ConvertibleToMethodValue
class OreForms @Inject()(implicit config: OreConfig, factory: ProjectFactory) {

val url = text verifying("error.url.invalid", text => {
if (text.isEmpty)
true
else {
try {
new URL(text)
true
} catch {
case _: MalformedURLException =>
false
}
}
})

/**
* Submits a member to be removed from a Project.
*/
Expand All @@ -42,10 +57,10 @@ class OreForms @Inject()(implicit config: OreConfig, factory: ProjectFactory) {
*/
lazy val ProjectSave = Form(mapping(
"category" -> text,
"issues" -> text,
"source" -> text,
"issues" -> url,
"source" -> url,
"license-name" -> text,
"license-url" -> text,
"license-url" -> url,
"description" -> text,
"users" -> list(number),
"roles" -> list(text),
Expand Down Expand Up @@ -79,7 +94,7 @@ class OreForms @Inject()(implicit config: OreConfig, factory: ProjectFactory) {
*/
lazy val OrganizationUpdateAvatar = Form(mapping(
"avatar-method" -> nonEmptyText,
"avatar-url" -> optional(nonEmptyText)
"avatar-url" -> optional(url)
)(OrganizationAvatarUpdate.apply)(OrganizationAvatarUpdate.unapply))

/**
Expand Down
1 change: 1 addition & 0 deletions app/views/bootstrap/layout.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<script type="text/javascript" src="@routes.Assets.at("javascripts/spongie.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/main.js")"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script>csrf = '@play.filters.csrf.CSRF.getToken.get.value'</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
Expand Down
2 changes: 2 additions & 0 deletions app/views/createOrganization.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@import models.user.role.OrganizationRole
@import ore.OreConfig
@import views.html.helper.form
@import views.html.helper.CSRF
@()(implicit messages: Messages, flash: Flash, request: Request[_], service: ModelService, config: OreConfig,
userBase: UserBase)

Expand All @@ -26,6 +27,7 @@ <h3 class="panel-title">
<p class="minor"> @messages("org.info")</p>

@form(action = routes.Organizations.create(), 'id -> "form-continue") {
@CSRF.formField
<div class="setting">
<div class="setting-description">
<h4>@messages("org.name")</h4>
Expand Down
61 changes: 44 additions & 17 deletions app/views/projects/channels/list.scala.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
@import controllers.project.{routes => projectRoutes}
@import db.ModelService
@import db.impl.access.UserBase
@import models.project.{Channel, Project}
@import ore.OreConfig
@import views.html.helper.form
@import views.html.helper.CSRF
@(project: Project, channels: Seq[Channel])(implicit messages: Messages, flash: Flash, request: Request[_],
service: ModelService, config: OreConfig, users: UserBase)

@projectRoutes = @{
controllers.project.routes.Projects
}

@channelRoutes = @{
controllers.project.routes.Channels
}

@versionRoutes = @{
controllers.project.routes.Versions
}

@bootstrap.layout(messages("channel.list.page-title", project.ownerName, project.slug)) {

<script type="text/javascript" src="@routes.Assets.at("javascripts/channelManage.js")"></script>
Expand All @@ -15,7 +28,7 @@
$(function() {
initChannelManager(
"#channel-new", "", "@config.defaultChannelColor.hex", "New channel",
"@projectRoutes.Channels.create(project.ownerName, project.slug)",
"@channelRoutes.create(project.ownerName, project.slug)",
"post", "Create channel"
);
});
Expand Down Expand Up @@ -54,21 +67,32 @@ <h3 class="panel-title">@messages("channel.list.title")</h3>
<i data-toggle="modal" data-target="#channel-settings"
id="channel-edit-@channel.id" class="fa fa-edit"></i>
</a>
<a id="channel-delete-@channel.id"
@if(channels.size == 1) {
data-toggle="tooltip" data-placement="top"
title="@messages("channel.edit.cannotDeleteLast")"
} else {

@if(channels.size == 1) {
<a id="channel-delete-@channel.id" data-toggle="tooltip"
data-placement="top"
title="@messages("channel.edit.cannotDeleteLast")">
<i class="fa fa-trash"></i>
</a>
} else {
@if(channel.versions.nonEmpty) {
data-toggle="modal" data-target="#modal-delete"
<a id="channel-delete-@channel.id" data-toggle="modal"
data-target="#modal-delete">
<i class="fa fa-trash"></i>
</a>
} else {
href="@projectRoutes.Channels.delete(
project.ownerName, project.slug, channel.name)"
@form(action = channelRoutes.delete(
project.ownerName, project.slug, channel.name),
'id -> s"form-delete-${channel.id.get}",
'class -> "form-channel-delete") {
@CSRF.formField
<a id="channel-delete-@channel.id.get" class="safe-delete"
data-channel-id="@channel.id.get">
<i class="fa fa-trash"></i>
</a>
}
}
}
>
<i class="fa fa-trash"></i>
</a>
}
</div>
</td>
</tr>
Expand All @@ -77,7 +101,7 @@ <h3 class="panel-title">@messages("channel.list.title")</h3>
initChannelDelete('#channel-delete-@channel.id', '@channel.name', @channel.versions.size);
initChannelManager(
"#channel-edit-@channel.id", "@channel.name", "@channel.color.hex",
"Edit channel", "@projectRoutes.Channels.save(
"Edit channel", "@channelRoutes.save(
project.ownerName, project.slug, channel.name)",
"post", "Save changes"
);
Expand All @@ -86,7 +110,7 @@ <h3 class="panel-title">@messages("channel.list.title")</h3>
}
</tbody>
</table>
<a href="@projectRoutes.Versions.showList(project.ownerName, project.slug, None)"
<a href="@versionRoutes.showList(project.ownerName, project.slug, None)"
class="pull-left btn btn-default">
<i class="fa fa-arrow-left"></i>
</a>
Expand Down Expand Up @@ -126,7 +150,10 @@ <h4 class="modal-title" id="label-delete">@messages("channel.delete")</h4>
<button type="button" class="btn btn-default" data-dismiss="modal">
@messages("channel.delete.close")
</button>
<a href="#" type="button" class="btn btn-danger">@messages("channel.delete")</a>
<form method="post" action="#" class="form-channel-delete">
@CSRF.formField
<button type="submit" class="btn btn-danger">@messages("channel.delete")</button>
</form>
</div>
</div>
</div>
Expand Down
4 changes: 3 additions & 1 deletion app/views/projects/channels/utils/modalManage.scala.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import ore.OreConfig
@import views.html.helper.form
@()(implicit messages: Messages, config: OreConfig)
@import views.html.helper.CSRF
@()(implicit messages: Messages, config: OreConfig, request: Request[_])

<div class="modal fade" id="channel-settings" tabindex="-1" role="dialog" aria-labelledBy="settings-label">
<div class="modal-dialog" role="document">
Expand All @@ -12,6 +13,7 @@
<h4 class="modal-title"></h4>
</div>
@form(action = routes.Application.showHome(None, None, None, None, None)) {
@CSRF.formField
<div class="modal-body">
<div class="form-inline">
<label for="channel-input">@messages("channel.name")</label>
Expand Down
4 changes: 3 additions & 1 deletion app/views/projects/create.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@import views.html.helper.form
@import ore.project.Dependency
@import ore.project.Dependency._
@import views.html.helper.CSRF
@(pending: Option[PendingProject])(implicit messages: Messages, flash: Flash, request: Request[_],
service: ModelService, config: OreConfig, users: UserBase)

Expand Down Expand Up @@ -119,6 +120,7 @@
<div class="create-buttons">
@* File controls *@
@form(action = projectRoutes.upload, 'enctype -> "multipart/form-data", 'id -> "form-upload") {
@CSRF.formField
<label class="btn btn-default pull-left" for="pluginFile">
<input id="pluginFile" name="pluginFile" type="file" style="display: none;">
<input id="pluginSig" name="pluginSig" type="file" style="display: none;">
Expand All @@ -131,7 +133,7 @@
@defining(pending.get.underlying) { project =>
@form(action = projectRoutes.showInvitationForm(project.ownerName, project.slug),
'id -> "continue", 'class -> "pull-right") {

@CSRF.formField
<div class="btn-group">
<a href="@projectRoutes.showCreator" title="Back" class="pull-left btn btn-default">
<i class="fa fa-arrow-left"></i>
Expand Down
3 changes: 3 additions & 0 deletions app/views/projects/invite.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

@import scala.collection.JavaConverters._
@import scala.concurrent.TimeoutException
@import views.html.helper.CSRF
@(pending: PendingProject)(implicit messages: Messages, flash: Flash, request: Request[_], service: ModelService,
forums: OreDiscourseApi, config: OreConfig, userBase: UserBase)

Expand Down Expand Up @@ -49,6 +50,8 @@
pending.underlying.slug),
'id -> "form-continue") {

@CSRF.formField

<div class="btn-group pull-right">
<a href="@projectRoutes.Projects.showCreatorWithMeta(
pending.underlying.ownerName,
Expand Down
5 changes: 5 additions & 0 deletions app/views/projects/settings.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
@import ore.permission.HideProjects
@import ore.permission.scope.GlobalScope
@import views.html.helper.form
@import views.html.helper.CSRF
@(project: Project)(implicit messages: Messages, flash: Flash, request: Request[_], service: ModelService,
config: OreConfig, userBase: UserBase)

Expand Down Expand Up @@ -70,6 +71,7 @@ <h4>Description</h4>
<!-- Project icon -->
<div class="setting">
<form id="form-icon" enctype="multipart/form-data">
@CSRF.formField
<div class="setting-description">
<h4>Icon</h4>

Expand Down Expand Up @@ -133,6 +135,7 @@ <h4 class="danger">Delete</h4>

@form(action = projectRoutes.save(project.ownerName, project.slug), 'id -> "save",
'class -> "pull-right") {
@CSRF.formField
<input type="hidden" id="update-icon" name="update-icon" value="false" />
<button type="submit" name="save" class="btn btn-success btn-spinner" data-icon="fa-check">
<i class="fa fa-check"></i> Save changes
Expand Down Expand Up @@ -173,6 +176,7 @@ <h4 class="modal-title" id="label-rename">@messages("project.rename.title")</h4>
<div class="modal-footer">
<div class="form-inline">
@form(action = projectRoutes.rename(project.ownerName, project.slug), 'id -> "rename") {
@CSRF.formField
<button type="button" class="btn btn-default" data-dismiss="modal">
@messages("channel.edit.close")
</button>
Expand All @@ -199,6 +203,7 @@ <h4 class="modal-title" id="label-delete">@messages("project.delete.title")</h4>
<div class="modal-footer">
<div class="form-inline">
@form(action = projectRoutes.delete(project.ownerName, project.slug)) {
@CSRF.formField
<button type="button" class="btn btn-default" data-dismiss="modal">
@messages("channel.edit.close")
</button>
Expand Down
Loading

0 comments on commit aa8d753

Please sign in to comment.