diff --git a/opentech/apply/activity/templatetags/activity_tags.py b/opentech/apply/activity/templatetags/activity_tags.py
index 1f43a872e263ae8585d4b1a0c4cf39cb1626868e..627b45bbe0d42807bba353873d09fd958fdbc2d4 100644
--- a/opentech/apply/activity/templatetags/activity_tags.py
+++ b/opentech/apply/activity/templatetags/activity_tags.py
@@ -12,7 +12,7 @@ register = template.Library()
 
 @register.filter
 def display_author(activity, user):
-    if user.is_applicant and isinstance(activity.related_object, Review):
+    if activity.submission.user == user and isinstance(activity.related_object, Review):
         return 'Reviewer'
     return activity.user
 
diff --git a/opentech/apply/dashboard/tests/test_views.py b/opentech/apply/dashboard/tests/test_views.py
index 54aba6a63a4a97204163699093cb308ddfde4440..eb3892c58c22ce5d71845e20ee5147eb889a16c7 100644
--- a/opentech/apply/dashboard/tests/test_views.py
+++ b/opentech/apply/dashboard/tests/test_views.py
@@ -4,12 +4,12 @@ from opentech.apply.funds.tests.factories import (
     InvitedToProposalFactory,
 )
 from opentech.apply.review.tests.factories import ReviewFactory, ReviewOpinionFactory
-from opentech.apply.users.tests.factories import UserFactory, ReviewerFactory, StaffFactory
+from opentech.apply.users.tests.factories import ApplicantFactory, ReviewerFactory, StaffFactory
 from opentech.apply.utils.testing.tests import BaseViewTestCase
 
 
 class TestApplicantDashboard(BaseViewTestCase):
-    user_factory = UserFactory
+    user_factory = ApplicantFactory
     url_name = 'dashboard:{}'
     base_view_name = 'dashboard'
 
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
index 0326bfbdfdcf20dceb7f9319c19c33d666d53e12..f8914d7bf67b0a7be99be705b423f9d1ddcdc34e 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
@@ -25,7 +25,7 @@
                 <span>Lead: {{ object.lead }}</span>
             {% endif %}
         </h5>
-        {% status_bar object.workflow object.phase request.user same_stage=True%}
+        {% status_bar object.workflow object.phase request.user author=object.user same_stage=True %}
 
         <div class="tabs js-tabs">
             <div class="tabs__container">
diff --git a/opentech/apply/funds/templatetags/statusbar_tags.py b/opentech/apply/funds/templatetags/statusbar_tags.py
index 99e4415b3d76af01871bc3fb85da32f257de8b9a..8b48c8b590dd0e298997c78ff1cfd7030d3bbd14 100644
--- a/opentech/apply/funds/templatetags/statusbar_tags.py
+++ b/opentech/apply/funds/templatetags/statusbar_tags.py
@@ -4,11 +4,12 @@ register = template.Library()
 
 
 @register.inclusion_tag('funds/includes/status_bar.html')
-def status_bar(workflow, current_phase, user, css_class='', same_stage=False):
+def status_bar(workflow, current_phase, user, author=False, css_class='', same_stage=False):
 
     phases = workflow.phases_for(user)
+    is_applicant = user == author if author else user.is_applicant
 
-    if same_stage and not user.is_applicant:
+    if same_stage and not is_applicant:
         phases = [
             phase for phase in phases
             if phase.stage == current_phase.stage
diff --git a/opentech/apply/funds/tests/factories/models.py b/opentech/apply/funds/tests/factories/models.py
index 5aca57fa69bc98e232e65ac850f3368579c60f1e..d31bd9bf205111216535b3bd09abd920281bd70c 100644
--- a/opentech/apply/funds/tests/factories/models.py
+++ b/opentech/apply/funds/tests/factories/models.py
@@ -28,7 +28,7 @@ from opentech.apply.funds.workflow import ConceptProposal, Request
 from opentech.apply.home.factories import ApplyHomePageFactory
 from opentech.apply.stream_forms.testing.factories import FormDataFactory
 from opentech.apply.users.groups import STAFF_GROUP_NAME, REVIEWER_GROUP_NAME
-from opentech.apply.users.tests.factories import StaffFactory, UserFactory, GroupFactory
+from opentech.apply.users.tests.factories import StaffFactory, ApplicantFactory, GroupFactory
 
 from . import blocks
 
@@ -241,7 +241,7 @@ class ApplicationSubmissionFactory(factory.DjangoModelFactory):
         workflow_name=factory.SelfAttribute('..workflow_name'),
         lead=factory.SelfAttribute('..lead'),
     )
-    user = factory.SubFactory(UserFactory)
+    user = factory.SubFactory(ApplicantFactory)
     lead = factory.SubFactory(StaffFactory)
     live_revision = None
     draft_revision = None
diff --git a/opentech/apply/funds/tests/test_views.py b/opentech/apply/funds/tests/test_views.py
index 41c17d983419f59cf29ac387d5680ac7e079c1a6..0ffbffe04da14593fbfc5c086703c9ee19fc300a 100644
--- a/opentech/apply/funds/tests/test_views.py
+++ b/opentech/apply/funds/tests/test_views.py
@@ -23,7 +23,7 @@ from opentech.apply.users.tests.factories import (
     ReviewerFactory,
     StaffFactory,
     SuperUserFactory,
-    UserFactory,
+    ApplicantFactory,
 )
 from opentech.apply.utils.testing import make_request
 from opentech.apply.utils.testing.tests import BaseViewTestCase
@@ -326,7 +326,7 @@ class TestReviewersUpdateView(BaseSubmissionViewTestCase):
 
 
 class TestApplicantSubmissionView(BaseSubmissionViewTestCase):
-    user_factory = UserFactory
+    user_factory = ApplicantFactory
 
     @classmethod
     def setUpTestData(cls):
@@ -420,7 +420,7 @@ class TestApplicantSubmissionView(BaseSubmissionViewTestCase):
 
 
 class TestRevisionsView(BaseSubmissionViewTestCase):
-    user_factory = UserFactory
+    user_factory = ApplicantFactory
 
     def test_create_revisions_on_submit(self):
         submission = ApplicationSubmissionFactory(status='draft_proposal', workflow_stages=2, user=self.user)
diff --git a/opentech/apply/funds/views.py b/opentech/apply/funds/views.py
index 0b05d75483ffeb19edfad866c72088a80c657f07..4d20af6f23161d026f26d1d76473a1c1d7da49d7 100644
--- a/opentech/apply/funds/views.py
+++ b/opentech/apply/funds/views.py
@@ -749,10 +749,8 @@ class PartnerSubmissionEditView(ApplicantSubmissionEditView):
         submission = self.get_object()
         # If the requesting user submitted the application, return the Applicant view.
         # Partners may somtimes be appliants as well.
-        if submission.user == request.user:
-            return ApplicantSubmissionEditView.as_view()(request, *args, **kwargs)
         partner_has_access = submission.partners.filter(pk=request.user.pk).exists()
-        if not partner_has_access:
+        if not partner_has_access and submission.user != request.user:
             raise PermissionDenied
         return super(ApplicantSubmissionEditView, self).dispatch(request, *args, **kwargs)
 
@@ -760,6 +758,7 @@ class PartnerSubmissionEditView(ApplicantSubmissionEditView):
 class SubmissionEditView(ViewDispatcher):
     admin_view = AdminSubmissionEditView
     applicant_view = ApplicantSubmissionEditView
+    reviewer_view = ApplicantSubmissionEditView
     partner_view = PartnerSubmissionEditView
 
 
diff --git a/opentech/apply/users/groups.py b/opentech/apply/users/groups.py
index 31887461c21ed6b096231790b4d80c21d0c7aad1..cc9cad3806bf3e4bf2dd4a435da1170dcbb10c0a 100644
--- a/opentech/apply/users/groups.py
+++ b/opentech/apply/users/groups.py
@@ -1,3 +1,4 @@
+APPLICANT_GROUP_NAME = 'Applicant'
 STAFF_GROUP_NAME = 'Staff'
 REVIEWER_GROUP_NAME = 'Reviewer'
 TEAMADMIN_GROUP_NAME = 'Team Admin'
@@ -6,13 +7,17 @@ COMMUNITY_REVIEWER_GROUP_NAME = 'Community reviewer'
 
 GROUPS = [
     {
-        'name': REVIEWER_GROUP_NAME,
+        'name': APPLICANT_GROUP_NAME,
         'permissions': [],
     },
     {
         'name': STAFF_GROUP_NAME,
         'permissions': [],
     },
+    {
+        'name': REVIEWER_GROUP_NAME,
+        'permissions': [],
+    },
     {
         'name': TEAMADMIN_GROUP_NAME,
         'permissions': [],
diff --git a/opentech/apply/users/migrations/0011_add_applicant_group.py b/opentech/apply/users/migrations/0011_add_applicant_group.py
new file mode 100644
index 0000000000000000000000000000000000000000..127b739aed4c749ba03ee4a5f181290522964b46
--- /dev/null
+++ b/opentech/apply/users/migrations/0011_add_applicant_group.py
@@ -0,0 +1,42 @@
+
+# Generated by Django 2.0.9 on 2018-12-19 13:21
+from __future__ import unicode_literals
+
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.management.sql import emit_post_migrate_signal
+from django.db import migrations
+
+from opentech.apply.users.groups import GROUPS, APPLICANT_GROUP_NAME
+
+
+def add_groups(apps, schema_editor):
+    # Workaround for https://code.djangoproject.com/ticket/23422
+    db_alias = schema_editor.connection.alias
+    emit_post_migrate_signal(2, False, db_alias)
+
+    Group = apps.get_model('auth.Group')
+    Permission = apps.get_model('auth.Permission')
+
+    for group_data in GROUPS:
+        group, created = Group.objects.get_or_create(name=group_data['name'])
+        for permission in group_data['permissions']:
+            try:
+                group.permissions.add(Permission.objects.get(codename=permission))
+            except ObjectDoesNotExist:
+                print("Could not find the '%s' permission" % permission)
+
+
+def remove_groups(apps, schema_editor):
+    Group = apps.get_model('auth.Group')
+    Group.objects.filter(name__in=[APPLICANT_GROUP_NAME]).delete()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0010_add_community_reviewer_group'),
+    ]
+
+    operations = [
+        migrations.RunPython(add_groups, remove_groups)
+    ]
diff --git a/opentech/apply/users/migrations/0012_set_applicant_group.py b/opentech/apply/users/migrations/0012_set_applicant_group.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c215af4c46d66e84c249a354516a915825dd3f2
--- /dev/null
+++ b/opentech/apply/users/migrations/0012_set_applicant_group.py
@@ -0,0 +1,39 @@
+
+# Generated by Django 2.0.9 on 2018-12-19 13:21
+from __future__ import unicode_literals
+
+from django.contrib.auth import get_user_model
+from django.contrib.auth.models import Group
+from django.db import migrations
+
+from opentech.apply.users.groups import APPLICANT_GROUP_NAME
+
+
+def set_group(apps, schema_editor):
+    User = get_user_model()
+    applicant_group = Group.objects.get(name=APPLICANT_GROUP_NAME)
+    applicants = User.objects.exclude(applicationsubmission=None)
+    for user in applicants:
+        if not user.is_apply_staff:
+            user.groups.add(applicant_group)
+            user.save()
+
+
+def unset_group(apps, schema_editor):
+    User = get_user_model()
+    applicant_group = Group.objects.get(name=APPLICANT_GROUP_NAME)
+    applicants = User.objects.filter(groups__name=APPLICANT_GROUP_NAME).all()
+    for user in applicants:
+        user.groups.remove(applicant_group)
+        user.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0011_add_applicant_group'),
+    ]
+
+    operations = [
+        migrations.RunPython(set_group, unset_group)
+    ]
diff --git a/opentech/apply/users/models.py b/opentech/apply/users/models.py
index 458f803ea4cc510d50274daf45c33a7a85863e05..9609eb97e1ebfdf0d7b2b5b866f828088fba333b 100644
--- a/opentech/apply/users/models.py
+++ b/opentech/apply/users/models.py
@@ -1,12 +1,11 @@
 from django.db import models
 from django.db.models import Q
 from django.contrib.auth.hashers import make_password
-from django.contrib.auth.models import AbstractUser, BaseUserManager
+from django.contrib.auth.models import AbstractUser, BaseUserManager, Group
 from django.urls import reverse
 from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
-
-from .groups import REVIEWER_GROUP_NAME, STAFF_GROUP_NAME, PARTNER_GROUP_NAME, COMMUNITY_REVIEWER_GROUP_NAME
+from .groups import APPLICANT_GROUP_NAME, REVIEWER_GROUP_NAME, STAFF_GROUP_NAME, PARTNER_GROUP_NAME, COMMUNITY_REVIEWER_GROUP_NAME
 from .utils import send_activation_email
 
 
@@ -25,6 +24,9 @@ class UserQuerySet(models.QuerySet):
     def community_reviewers(self):
         return self.filter(groups__name=COMMUNITY_REVIEWER_GROUP_NAME)
 
+    def applicants(self):
+        return self.filter(groups__name=APPLICANT_GROUP_NAME)
+
 
 class UserManager(BaseUserManager.from_queryset(UserQuerySet)):
     use_in_migrations = True
@@ -65,6 +67,9 @@ class UserManager(BaseUserManager.from_queryset(UserQuerySet)):
         user, created = self.get_or_create(defaults=defaults, **kwargs)
         if created:
             send_activation_email(user, site)
+            applicant_group = Group.objects.get(name=APPLICANT_GROUP_NAME)
+            user.groups.add(applicant_group)
+            user.save()
         return user, created
 
 
@@ -125,7 +130,7 @@ class User(AbstractUser):
 
     @cached_property
     def is_applicant(self):
-        return not self.is_apply_staff and not self.is_reviewer and not self.is_partner
+        return self.groups.filter(name=APPLICANT_GROUP_NAME).exists()
 
     class Meta:
         ordering = ('full_name', 'email')
diff --git a/opentech/apply/users/tests/factories.py b/opentech/apply/users/tests/factories.py
index b111108c871b44f89780a9472a3c68b3c3d2dedd..8db74b40f779c61361dc8f2b05e6805015b70cb5 100644
--- a/opentech/apply/users/tests/factories.py
+++ b/opentech/apply/users/tests/factories.py
@@ -3,7 +3,7 @@ from django.contrib.auth.models import Group
 
 import factory
 
-from ..groups import REVIEWER_GROUP_NAME, STAFF_GROUP_NAME
+from ..groups import APPLICANT_GROUP_NAME, REVIEWER_GROUP_NAME, STAFF_GROUP_NAME
 
 
 class GroupFactory(factory.DjangoModelFactory):
@@ -66,3 +66,10 @@ class ReviewerFactory(UserFactory):
     def groups(self, create, extracted, **kwargs):
         if create:
             self.groups.add(GroupFactory(name=REVIEWER_GROUP_NAME))
+
+
+class ApplicantFactory(UserFactory):
+    @factory.post_generation
+    def groups(self, create, extracted, **kwargs):
+        if create:
+            self.groups.add(GroupFactory(name=APPLICANT_GROUP_NAME))