Index: main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 6693)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 6694)
@@ -65,5 +65,6 @@
     IStudentsContainer, IStudent, IStudentClearance,
     IStudentPersonal, IStudentBase, IStudentStudyCourse,
-    IStudentPayments, IStudentAccommodation, IStudentNavigation
+    IStudentPayments, IStudentAccommodation, IStudentNavigation,
+    IStudentBaseEdit, 
     )
 from waeup.sirp.students.student import Student
@@ -233,5 +234,5 @@
     grok.require('waeup.viewStudent')
     grok.template('studentpage')
-    form_fields = grok.AutoFields(IStudentBase)
+    form_fields = grok.AutoFields(IStudentBase).omit('password')
     pnav = 4
     title = 'Base Data'
@@ -447,2 +448,45 @@
     def label(self):
         return '%s: History' % self.context.name
+
+# Pages for students only
+
+class StudentBaseEditActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    text = 'Change password'
+    target = 'bedit'
+
+class StudentBaseEditFormPage(WAeUPEditFormPage):
+    """ View to edit student base data by student
+    """
+    grok.context(IStudent)
+    grok.name('bedit')
+    grok.require('waeup.handleStudent')
+    form_fields = grok.AutoFields(IStudentBaseEdit).omit('student_id')
+    grok.template('studentbaseeditpage')
+    label = 'Change password'
+    title = 'Base Data'
+    pnav = 4
+
+    def update(self):
+        datepicker.need() # Enable jQuery datepicker in date fields.
+        super(StudentBaseEditFormPage, self).update()
+        self.wf_info = IWorkflowInfo(self.context)
+        return
+
+    @grok.action('Save')
+    def save(self, **data):
+        changed_fields = self.applyData(self.context, **data)
+        changed_fields = changed_fields.values()
+        fields_string = '+'.join(' + '.join(str(i) for i in b) for b in changed_fields)
+        self.context._p_changed = True
+        self.flash('Form has been saved.')
+        form = self.request.form
+        ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
+        if fields_string:
+            self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
+        if 'password' in fields_string:
+            IUserAccount(self.context).setPassword(form['form.password'])
+        return
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/studentbaseeditpage.pt
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/studentbaseeditpage.pt	(revision 6694)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/studentbaseeditpage.pt	(revision 6694)
@@ -0,0 +1,48 @@
+<h2 i18n:translate=""
+    tal:condition="view/label"
+    tal:content="view/label">Label</h2>
+
+<form action="." tal:attributes="action request/URL" method="post"
+      class="edit-form" enctype="multipart/form-data">
+
+  <div class="form-status"
+    tal:define="status view/status"
+    tal:condition="status">
+    Form Status:
+    <span i18n:translate="" tal:content="view/status">
+      Form status summary
+    </span>
+  </div>
+
+  <table class="form-fields zebra">
+    <tbody>
+      <tal:block repeat="widget view/widgets">
+        <tr>
+          <td class="label">
+            <label tal:attributes="for widget/name">
+              <span class="required" tal:condition="widget/required">*</span>
+              <span i18n:translate="" tal:content="widget/label">label</span>:
+            </label>
+          </td>
+          <td class="field">
+            <span class="widget" tal:content="structure widget">
+              <input type="text" />
+            </span>
+            <tal:error tal:condition="widget/error">
+              <span tal:replace="structure widget/error">error</span>
+            </tal:error>
+            <tal:hint tal:condition="widget/hint">
+              <span class="hint" tal:content="structure widget/hint">hint</span>
+            </tal:hint>
+          </td>
+        </tr>
+      </tal:block>
+    </tbody>
+  </table>
+
+  <div class="actionButtons" tal:condition="view/availableActions">
+    <input tal:repeat="action view/actions"
+           tal:replace="structure action/render"
+           />
+  </div>
+</form>
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py	(revision 6693)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py	(revision 6694)
@@ -61,5 +61,5 @@
     history = Attribute('Object history, a list of messages.')
     state = Attribute('Returns the registration state of a student')
-    student_id = Attribute('Randomly generated id')
+    #student_id = Attribute('Randomly generated id')
 
     def loggerInfo(ob_class, comment):
@@ -78,5 +78,5 @@
         )
 
-    password = schema.TextLine(
+    password = schema.Password(
         title = u'Password',
         )
@@ -126,2 +126,24 @@
     """
 
+# Interfaces for students only
+
+class IStudentBaseEdit(IStudentBase):
+    """Interface needed for editing of student base data by students.
+    """
+
+    name = schema.TextLine(
+        title = u'Full Name',
+        default = u'Nobody',
+        required = True,
+        readonly = True,
+        )
+
+IStudentBaseEdit['name'].order =  IStudentBase['name'].order
+
+class IStudentClearanceEdit(IStudentClearance):
+    """Interface needed for restricted editing of student clearance data.
+    """
+
+class IStudentPersonalEdit(IStudentPersonal):
+    """Interface needed for restricted editing of student personal data.
+    """
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/student.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/student.py	(revision 6693)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/student.py	(revision 6694)
@@ -23,5 +23,7 @@
 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
 from waeup.sirp.interfaces import IObjectHistory
-from waeup.sirp.students.interfaces import IStudent, IStudentNavigation
+from waeup.sirp.students.interfaces import (
+    IStudent, IStudentNavigation, IStudentBaseEdit,
+    )
 from waeup.sirp.utils.helpers import attrs_to_fields
 from waeup.sirp.students.utils import generate_student_id
@@ -31,5 +33,6 @@
     owned by students.
     """
-    grok.implements(IStudent, IStudentNavigation)
+    grok.implements(IStudent, IStudentNavigation,
+        IStudentBaseEdit)
     grok.provides(IStudent)
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 6693)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 6694)
@@ -39,4 +39,5 @@
 from waeup.sirp.university.faculty import Faculty
 from waeup.sirp.university.department import Department
+from waeup.sirp.interfaces import IUserAccount
 
 PH_LEN = 2059  # Length of placeholder file
@@ -75,5 +76,8 @@
         student.name = u'Anna Tester'
         self.test_student_id = self.app['students'].addStudent(student)
-
+        # Set password
+        IUserAccount(self.app['students'][self.test_student_id]).setPassword('spwd')
+
+        self.login_path = 'http://localhost/app/login'
         self.container_path = 'http://localhost/app/students'
         self.manage_container_path = self.container_path + '/@@manage'
@@ -244,4 +248,35 @@
         self.assertMatches('...Student admitted by zope.mgr...',
                            self.browser.contents)
-
-        return
+        return
+
+    def test_student_access(self):
+        # Students can access their own objects
+        # and can perform actions
+
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.test_student_id
+        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl("Login").click()
+        self.assertEqual(self.browser.url, self.student_path)
+        self.assertTrue('You logged in' in self.browser.contents)
+        # Change password
+        self.browser.getLink("Change password").click()
+        self.browser.getControl(name="form.password").value = 'new_password'
+        self.browser.getControl("Save").click()
+        self.assertTrue('Form has been saved' in self.browser.contents)
+        # We are still logged in. Changing the password hasn't thrown us out.
+        self.browser.getLink("My Data").click()
+        self.assertEqual(self.browser.url, self.student_path)
+        # We can logout
+        self.browser.getLink("Logout").click()
+        self.assertTrue('You have been logged out' in self.browser.contents)
+        self.assertEqual(self.browser.url, 'http://localhost/app')
+        # We can login again with the new password
+        self.browser.getLink("Login").click()
+        #self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.test_student_id
+        self.browser.getControl(name="form.password").value = 'new_password'
+        self.browser.getControl("Login").click()
+        self.assertEqual(self.browser.url, self.student_path)
+        self.assertTrue('You logged in' in self.browser.contents)
+        return
