diff --git a/opentech/apply/activity/messaging.py b/opentech/apply/activity/messaging.py
index 084dc735497bf38978988518acc5b736eb2bda13..eb6405e039f5642b97f60e257659e893ce728d10 100644
--- a/opentech/apply/activity/messaging.py
+++ b/opentech/apply/activity/messaging.py
@@ -55,6 +55,7 @@ neat_related = {
     MESSAGES.SCREENING: 'old_status',
     MESSAGES.REVIEW_OPINION: 'opinion',
     MESSAGES.DELETE_REVIEW: 'review',
+    MESSAGES.EDIT_REVIEW: 'review',
 }
 
 
@@ -369,6 +370,7 @@ class SlackAdapter(AdapterBase):
         MESSAGES.BATCH_READY_FOR_REVIEW: 'batch_notify_reviewers',
         MESSAGES.DELETE_SUBMISSION: '{user} has deleted {submission.title}',
         MESSAGES.DELETE_REVIEW: '{user} has deleted {review.author} review for <{link}|{submission.title}>.',
+        MESSAGES.EDIT_REVIEW: '{user} has edited {review.author} review for <{link}|{submission.title}>.',
     }
 
     def __init__(self):
diff --git a/opentech/apply/activity/migrations/0024_add_review_edit_event.py b/opentech/apply/activity/migrations/0024_add_review_edit_event.py
new file mode 100644
index 0000000000000000000000000000000000000000..e1387495ab149a6d52d161c1b880e3b4bda4dadf
--- /dev/null
+++ b/opentech/apply/activity/migrations/0024_add_review_edit_event.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.0.13 on 2019-07-14 09:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('activity', '0023_notify_partners'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='event',
+            name='type',
+            field=models.CharField(choices=[('UPDATE_LEAD', 'Update Lead'), ('EDIT', 'Edit'), ('APPLICANT_EDIT', 'Applicant Edit'), ('NEW_SUBMISSION', 'New Submission'), ('SCREENING', 'Screening'), ('TRANSITION', 'Transition'), ('BATCH_TRANSITION', 'Batch Transition'), ('DETERMINATION_OUTCOME', 'Determination Outcome'), ('BATCH_DETERMINATION_OUTCOME', 'Batch Determination Outcome'), ('INVITED_TO_PROPOSAL', 'Invited To Proposal'), ('REVIEWERS_UPDATED', 'Reviewers Updated'), ('BATCH_REVIEWERS_UPDATED', 'Batch Reviewers Updated'), ('PARTNERS_UPDATED', 'Partners Updated'), ('PARTNERS_UPDATED_PARTNER', 'Partners Updated Partner'), ('READY_FOR_REVIEW', 'Ready For Review'), ('BATCH_READY_FOR_REVIEW', 'Batch Ready For Review'), ('NEW_REVIEW', 'New Review'), ('COMMENT', 'Comment'), ('PROPOSAL_SUBMITTED', 'Proposal Submitted'), ('OPENED_SEALED', 'Opened Sealed Submission'), ('REVIEW_OPINION', 'Review Opinion'), ('DELETE_SUBMISSION', 'Delete Submission'), ('DELETE_REVIEW', 'Delete Review'), ('EDIT_REVIEW', 'Edit Review')], max_length=50),
+        ),
+    ]
diff --git a/opentech/apply/activity/options.py b/opentech/apply/activity/options.py
index 6e9a914cf5025a84da0b72d3e2cb54993b57f3f5..1fd7988a748fff6ca610a28d3f8c6210913204f5 100644
--- a/opentech/apply/activity/options.py
+++ b/opentech/apply/activity/options.py
@@ -26,6 +26,7 @@ class MESSAGES(Enum):
     REVIEW_OPINION = 'Review Opinion'
     DELETE_SUBMISSION = 'Delete Submission'
     DELETE_REVIEW = 'Delete Review'
+    EDIT_REVIEW = 'Edit Review'
 
     @classmethod
     def choices(cls):
diff --git a/opentech/apply/review/templates/review/review_detail.html b/opentech/apply/review/templates/review/review_detail.html
index 33d224fc9ef888f3cca1eb9ce70e44037f934db0..20264332d8a1482f0609d56d7be9784e5d3af604 100644
--- a/opentech/apply/review/templates/review/review_detail.html
+++ b/opentech/apply/review/templates/review/review_detail.html
@@ -24,7 +24,7 @@
         <svg class="icon icon--eye"><use xlink:href="#eye"></use></svg>
         {{ review.get_visibility_display }}
     </div>
-    {% if perms.funds.delete_review or request.user == review.author %}
+    {% if perms.funds.delete_review or request.user == review.author.reviewer %}
         <div>
             <a class="link link--delete-review is-active" href="{% url 'apply:submissions:reviews:delete' submission_pk=object.submission.id pk=object.id %}">
                 Delete
@@ -32,6 +32,14 @@
             </a>
         </div>
     {% endif %}
+    {% if perms.funds.change_review or request.user == review.author.reviewer %}
+        <div>
+            <a class="link link--edit-review is-active" href="{% url 'apply:submissions:reviews:edit' submission_pk=object.submission.id pk=object.id %}">
+                Edit
+                <svg class="icon icon--pen"><use xlink:href="#pen"></use></svg>
+            </a>
+        </div>
+    {% endif %}
     {% if not review.for_latest %}
         <div>
             <h5>Review was not against the latest version:</h5>
diff --git a/opentech/apply/review/templates/review/review_edit_form.html b/opentech/apply/review/templates/review/review_edit_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..c027c4b2ca3c8a8c7fc2eb27ac64d85fe3ba37cc
--- /dev/null
+++ b/opentech/apply/review/templates/review/review_edit_form.html
@@ -0,0 +1,44 @@
+{% extends "base-apply.html" %}
+{% block title %}Edit a review{% endblock %}
+{% block content %}
+<div class="admin-bar">
+    <div class="admin-bar__inner">
+        <h1 class="beta heading heading--no-margin heading--bold">{{ title|default:"Edit Review" }}</h1>
+        <h5>For <a href="{% url "funds:submissions:detail" submission.id %}">{{ submission.title }}</a></h5>
+    </div>
+</div>
+
+{% include "forms/includes/form_errors.html" with form=form %}
+
+<div class="wrapper wrapper--medium wrapper--inner-space-medium">
+<form class="form form--with-p-tags form--scoreable" action="" method="post" novalidate>
+    {{ form.media }}
+    {% csrf_token %}
+
+    {% for hidden in form.hidden_fields %}
+        {{ hidden }}
+    {% endfor %}
+
+    {% for field in form.visible_fields %}
+        {# to be replaced with better logic when we use stream form #}
+        {% ifchanged field.field.group %}
+            {% for key, value in form.titles.items %}
+                {% if key == field.field.group %}
+                    <h2>{{ value }}</h2>
+                {% endif %}
+            {% endfor %}
+        {% endifchanged %}
+
+        {% if field.field %}
+            {% include "forms/includes/field.html" %}
+        {% else %}
+            {{ field }}
+        {% endif %}
+    {% endfor %}
+    {% if not object.id or object.is_draft %}
+        <input class="button button--submit button--top-space button--white" type="submit" value="Save Draft" name="{{ form.draft_button_name }}" />
+    {% endif %}
+    <input class="button button--submit button--top-space button--primary" type="submit" value="Submit" name="submit" />
+</form>
+</div>
+{% endblock %}
diff --git a/opentech/apply/review/urls.py b/opentech/apply/review/urls.py
index 2d632fb1cddd25f1ee42b697acba11c72ffe2d67..e7d575eb459f3a45cfe9f8b30c69dddc7825d5c7 100644
--- a/opentech/apply/review/urls.py
+++ b/opentech/apply/review/urls.py
@@ -1,6 +1,6 @@
 from django.urls import path
 
-from .views import ReviewDetailView, ReviewListView, ReviewCreateOrUpdateView, ReviewDeleteView
+from .views import ReviewDetailView, ReviewListView, ReviewCreateOrUpdateView, ReviewDeleteView, ReviewEditView
 
 app_name = 'reviews'
 
@@ -8,5 +8,6 @@ urlpatterns = [
     path('reviews/', ReviewListView.as_view(), name='list'),
     path('reviews/<int:pk>/', ReviewDetailView.as_view(), name="review"),
     path('reviews/<int:pk>/delete/', ReviewDeleteView.as_view(), name="delete"),
+    path('reviews/<int:pk>/edit/', ReviewEditView.as_view(), name="edit"),
     path('review/', ReviewCreateOrUpdateView.as_view(), name='form'),
 ]
diff --git a/opentech/apply/review/views.py b/opentech/apply/review/views.py
index 7b22550b16c81f0a9901b5f265bae3bfeb5ac861..15fe39ba7e28dad31b7826e452353713061ac48f 100644
--- a/opentech/apply/review/views.py
+++ b/opentech/apply/review/views.py
@@ -6,7 +6,7 @@ from django.shortcuts import get_object_or_404
 from django.template.loader import get_template
 from django.urls import reverse_lazy
 from django.utils.decorators import method_decorator
-from django.views.generic import CreateView, ListView, DetailView, DeleteView
+from django.views.generic import CreateView, ListView, DetailView, DeleteView, UpdateView
 
 from wagtail.core.blocks import RichTextBlock
 
@@ -53,6 +53,56 @@ def get_fields_for_stage(submission):
         return forms[0].form.form_fields
 
 
+class ReviewEditView(UserPassesTestMixin, BaseStreamForm, UpdateView):
+    submission_form_class = ReviewModelForm
+    model = Review
+    template_name = 'review/review_edit_form.html'
+    raise_exception = True
+
+    def test_func(self):
+        review = self.get_object()
+        return self.request.user.has_perm('review.change_review') or self.request.user == review.author.reviewer
+
+    def get_context_data(self, **kwargs):
+        review = self.get_object()
+        return super().get_context_data(
+            submission=review.submission,
+            title="Edit Review",
+            **kwargs
+        )
+
+    def get_defined_fields(self):
+        review = self.get_object()
+        return get_fields_for_stage(review.submission)
+
+    def get_form_kwargs(self):
+        review = self.get_object()
+        kwargs = super().get_form_kwargs()
+        kwargs['user'] = self.request.user
+        kwargs['submission'] = review.submission
+
+        if self.object:
+            kwargs['initial'] = self.object.form_data
+
+        return kwargs
+
+    def form_valid(self, form):
+        review = self.get_object()
+        messenger(
+            MESSAGES.EDIT_REVIEW,
+            user=self.request.user,
+            request=self.request,
+            submission=review.submission,
+            related=review,
+        )
+        response = super().form_valid(form)
+        return response
+
+    def get_success_url(self):
+        review = self.get_object()
+        return reverse_lazy('funds:submissions:detail', args=(review.submission.id,))
+
+
 @method_decorator(login_required, name='dispatch')
 class ReviewCreateOrUpdateView(BaseStreamForm, CreateOrUpdateView):
     submission_form_class = ReviewModelForm
@@ -167,7 +217,7 @@ class ReviewDisplay(UserPassesTestMixin, DetailView):
     def test_func(self):
         review = self.get_object()
         user = self.request.user
-        author = review.author
+        author = review.author.reviewer
         submission = review.submission
         partner_has_access = submission.partners.filter(pk=user.pk).exists()
 
@@ -213,7 +263,7 @@ class ReviewOpinionFormView(UserPassesTestMixin, CreateView):
     def test_func(self):
         review = self.get_object()
         user = self.request.user
-        author = review.author
+        author = review.author.reviewer
         submission = review.submission
         partner_has_access = submission.partners.filter(pk=user.pk).exists()