Changeset 5611

Show
Ignore:
Timestamp:
07/27/12 17:06:27 (7 years ago)
Author:
gpress
Message:

Addresses ticket #687, editable Seattle profile data. Affiliation, email and password are now editable by the Seattle Clearinghouse user. Code to edit user port also added but not enabled.

Views.py was in Windows/Dos format, this commit converts it back to Unix.

Location:
seattle/trunk/seattlegeni
Files:
1 added
6 modified

Legend:

Unmodified
Added
Removed
  • seattle/trunk/seattlegeni/common/api/maindb.py

    r3647 r5611  
    320320 
    321321@log_function_call 
     322def set_user_email(geniuser, new_email): 
     323  """ 
     324  <Purpose> 
     325    Sets the email for the geniuser. 
     326  <Arguments> 
     327    geniuser 
     328      The GeniUser object of the user whose email is to be changed. 
     329    new_email   
     330      The new email value. 
     331  <Exceptions> 
     332    None 
     333  <Side Effects> 
     334    Updates the database as well as the geniuser object passed in with the 
     335    provided email. 
     336  <Returns> 
     337    None 
     338  """ 
     339  assert_geniuser(geniuser) 
     340   
     341  geniuser.email = new_email 
     342  geniuser.save() 
     343 
     344 
     345 
     346 
     347 
     348@log_function_call 
     349def set_user_affiliation(geniuser, new_affiliation): 
     350  """ 
     351  <Purpose> 
     352    Sets the affiliation for the geniuser. 
     353  <Arguments> 
     354    geniuser 
     355      The GeniUser object of the user whose affiliation is to be changed. 
     356    new_affiliation   
     357      The new affiliation value. 
     358  <Exceptions> 
     359    None 
     360  <Side Effects> 
     361    Updates the database as well as the geniuser object passed in with the 
     362    provided affiliation. 
     363  <Returns> 
     364    None 
     365  """ 
     366  assert_geniuser(geniuser) 
     367   
     368  geniuser.affiliation = new_affiliation 
     369  geniuser.save() 
     370 
     371 
     372 
     373 
     374 
     375@log_function_call 
     376def set_user_port(geniuser, new_port): # currently not in use  
     377  """ 
     378  <Purpose> 
     379    Sets the port for the geniuser. 
     380  <Arguments> 
     381    geniuser 
     382      The GeniUser object of the user whose port is to be changed. 
     383    new_port   
     384      The new port value. 
     385  <Exceptions> 
     386    None 
     387  <Side Effects> 
     388    Updates the database as well as the geniuser object passed in with the 
     389    provided port. 
     390  <Returns> 
     391    None 
     392  """ 
     393  # if new_port in ALLOWED_USER_PORTS: 
     394  assert_geniuser(geniuser) 
     395   
     396  geniuser.usable_vessel_port = new_port 
     397  geniuser.save() 
     398 
     399 
     400 
     401 
     402 
     403@log_function_call_and_only_first_argument 
     404def set_user_password(geniuser, new_password): 
     405  """ 
     406  <Purpose> 
     407    Sets the password for the geniuser. 
     408  <Arguments> 
     409    geniuser 
     410      The GeniUser object of the user whose password is to be changed. 
     411    new_password   
     412      The new password value. 
     413  <Exceptions> 
     414    None 
     415  <Side Effects> 
     416    Updates the database as well as the geniuser object passed in with the 
     417    provided password. 
     418  <Returns> 
     419    None 
     420  """ 
     421  assert_geniuser(geniuser) 
     422 
     423  # Set the password using this function so that it gets hashed by django. 
     424  geniuser.set_password(new_password) 
     425  geniuser.save() 
     426 
     427 
     428 
     429 
     430 
     431@log_function_call 
    322432def create_node(node_identifier, last_known_ip, last_known_port, last_known_version, is_active, owner_pubkey, extra_vessel_name): 
    323433  """ 
     
    378488 
    379489 
     490def get_allowed_user_ports(): 
     491  """ 
     492  <Purpose> 
     493    Gets the allowed user ports defined globally in this file. 
     494  <Arguments> 
     495    None 
     496  <Exceptions> 
     497    None 
     498  <Side Effects> 
     499    None 
     500  <Returns> 
     501    The allowed user ports which are a list. 
     502  """ 
     503  return ALLOWED_USER_PORTS 
     504 
     505 
     506 
     507 
     508 
    380509@log_function_call 
    381510def create_donation(node, donor, resource_description_text): 
  • seattle/trunk/seattlegeni/website/control/interface.py

    r5494 r5611  
    442442 
    443443 
     444         
     445def get_useable_ports(): 
     446  """ 
     447  <Purpose> 
     448     Gets the allowed user port range 
     449  <Arguments> 
     450        None 
     451  <Exceptions> 
     452   None 
     453  <Side Effects> 
     454    None 
     455  <Returns> 
     456    The allowed user port range which is globally defined in maindb. 
     457  """ 
     458  return maindb.get_allowed_user_ports() 
     459 
     460 
     461 
     462 
     463 
     464@log_function_call 
     465def change_user_email(geniuser, new_email): 
     466  """ 
     467  <Purpose> 
     468     Sets a new email for the user  
     469  <Arguments> 
     470    geniuser 
     471      A GeniUser object of the user whose email is to be updated. 
     472    new_email 
     473      the new email value 
     474  <Exceptions> 
     475    ValidationError 
     476      If the email is provided and is invalid. 
     477  <Side Effects> 
     478    The geniuser email gets changed to the new value(in the db). 
     479  <Returns> 
     480    None 
     481  """ 
     482  assert_geniuser(geniuser) 
     483  #validate its a real email.  The frontend should already 
     484  #checks for this but we validate again just in case. 
     485  validations.validate_email(new_email) 
     486  
     487  # Lock the user. 
     488  lockserver_handle = lockserver.create_lockserver_handle() 
     489  lockserver.lock_user(lockserver_handle, geniuser.username) 
     490  try: 
     491    # Make sure the user still exists now that we hold the lock. Also makes 
     492    # sure that we see any changes made to the user before we obtained the lock. 
     493    # We don't use the user object we retrieve because we want the 
     494    # object passed in to the function to reflect changes we make to the object. 
     495    try: 
     496      maindb.get_user(geniuser.username) 
     497    except DoesNotExistError: 
     498      raise InternalError(traceback.format_exc()) 
     499 
     500    maindb.set_user_email(geniuser, new_email) 
     501  finally: 
     502    # Unlock the user. 
     503    lockserver.unlock_user(lockserver_handle, geniuser.username) 
     504    lockserver.destroy_lockserver_handle(lockserver_handle) 
     505 
     506 
     507 
     508 
     509 
     510@log_function_call 
     511def change_user_affiliation(geniuser, new_affiliation): 
     512  """ 
     513  <Purpose> 
     514     Sets a new affiliation for the user  
     515  <Arguments> 
     516    geniuser 
     517      A GeniUser object of the user whose affiliation is to be updated. 
     518    new_affiliation 
     519      the new affiliation value 
     520  <Exceptions> 
     521    ValidationError 
     522      If the affiliation is provided and is invalid. 
     523  <Side Effects> 
     524    The geniuser affiliation gets changed to the new value(in the db). 
     525  <Returns> 
     526    None 
     527  """ 
     528  assert_geniuser(geniuser) 
     529  #Determines if the new affiliation is valid.  The frontend should already 
     530  #checks for this but we validate again here just in case. 
     531  validations.validate_affiliation(new_affiliation) 
     532  
     533   
     534  # Lock the user. 
     535  lockserver_handle = lockserver.create_lockserver_handle() 
     536  lockserver.lock_user(lockserver_handle, geniuser.username) 
     537  try: 
     538    # Make sure the user still exists now that we hold the lock. Also makes 
     539    # sure that we see any changes made to the user before we obtained the lock. 
     540    # We don't use the user object we retrieve because we want the 
     541    # object passed in to the function to reflect changes we make to the object. 
     542    try: 
     543      maindb.get_user(geniuser.username) 
     544    except DoesNotExistError: 
     545      raise InternalError(traceback.format_exc()) 
     546 
     547    maindb.set_user_affiliation(geniuser, new_affiliation) 
     548  finally: 
     549    # Unlock the user. 
     550    lockserver.unlock_user(lockserver_handle, geniuser.username) 
     551    lockserver.destroy_lockserver_handle(lockserver_handle) 
     552 
     553 
     554 
     555 
     556 
     557@log_function_call 
     558def change_user_port(geniuser, new_port): 
     559  """ 
     560  <Purpose> 
     561     Sets a new port for the user  
     562  <Arguments> 
     563    geniuser 
     564      A GeniUser object of the user whose port is to be changed. 
     565    new_port 
     566      the new port value 
     567  <Exceptions> 
     568    ValidationError 
     569      If the port is provided and it is not in the allowed range. 
     570  <Side Effects> 
     571    the geniuser port gets changed to the new value(in the db). 
     572  <Returns> 
     573    None 
     574  """ 
     575  assert_geniuser(geniuser) 
     576 
     577  # Lock the user. 
     578  lockserver_handle = lockserver.create_lockserver_handle() 
     579  lockserver.lock_user(lockserver_handle, geniuser.username) 
     580  try: 
     581    # Make sure the user still exists now that we hold the lock. Also makes 
     582    # sure that we see any changes made to the user before we obtained the lock. 
     583    # We don't use the user object we retrieve because we want the 
     584    # object passed in to the function to reflect changes we make to the object. 
     585    try: 
     586      maindb.get_user(geniuser.username) 
     587    except DoesNotExistError: 
     588      raise InternalError(traceback.format_exc()) 
     589 
     590    maindb.set_user_port(geniuser, new_port) 
     591  finally: 
     592    # Unlock the user. 
     593    lockserver.unlock_user(lockserver_handle, geniuser.username) 
     594    lockserver.destroy_lockserver_handle(lockserver_handle) 
     595 
     596 
     597 
     598 
     599         
     600@log_function_call_and_only_first_argument 
     601def change_user_password(geniuser, new_password): 
     602  """ 
     603  <Purpose> 
     604     Sets a new password for the geniuser.  
     605  <Arguments> 
     606    geniuser 
     607      A GeniUser object of the user whose password is to be changed. 
     608    new_password 
     609      the user specificed new password value. 
     610  <Exceptions> 
     611    ValidationError 
     612      If the password is provided and is invalid. 
     613  <Side Effects> 
     614    The geniuser password gets changed to the new value (in the db). 
     615  <Returns> 
     616    None 
     617  """ 
     618  assert_geniuser(geniuser) 
     619  #Determines if the new password is strong enough.  The frontend should already 
     620  #check for this but we validate again here just in case. 
     621  validations.validate_password(new_password) 
     622   
     623  # Lock the user. 
     624  lockserver_handle = lockserver.create_lockserver_handle() 
     625  lockserver.lock_user(lockserver_handle, geniuser.username) 
     626  try: 
     627    # Make sure the user still exists now that we hold the lock. Also makes 
     628    # sure that we see any changes made to the user before we obtained the lock. 
     629    # We don't use the user object we retrieve because we want the 
     630    # object passed in to the function to reflect changes we make to the object. 
     631    try: 
     632      maindb.get_user(geniuser.username) 
     633    except DoesNotExistError: 
     634      raise InternalError(traceback.format_exc()) 
     635 
     636    maindb.set_user_password(geniuser, new_password) 
     637  finally: 
     638    # Unlock the user. 
     639    lockserver.unlock_user(lockserver_handle, geniuser.username) 
     640    lockserver.destroy_lockserver_handle(lockserver_handle) 
     641 
     642 
     643 
     644 
    444645 
    445646@log_function_call 
  • seattle/trunk/seattlegeni/website/html/forms.py

    r3269 r5611  
    1818  http://docs.djangoproject.com/en/dev/topics/forms/ 
    1919""" 
     20from seattlegeni.website.control.models import GeniUser 
    2021 
    2122from django.contrib.auth.forms import UserCreationForm as DjangoUserCreationForm 
     
    9293 
    9394 
     95 
     96 
     97def gen_edit_user_form(field_list=None, *args, **kwargs): 
     98  """ 
     99  <Purpose> 
     100      Dynamically generates a EditUserForm depending on field_list. 
     101 
     102  <Arguments> 
     103      field_list: 
     104          The profile view passes in the desired field that will be edited by the 
     105          EditUserForm. 
     106 
     107  <Exceptions> 
     108      ValidationErrors raised by a incorrect field value. 
     109 
     110  <Side Effects> 
     111      None. 
     112 
     113  <Returns> 
     114      A EditUserForm object that is specific to the field list passed in. 
     115 
     116  """ 
     117  class EditUserForm(forms.ModelForm): 
     118    class Meta: 
     119      model = GeniUser 
     120      fields = field_list 
     121       
     122    def __init__(self): 
     123      super(EditUserForm, self).__init__(*args, **kwargs) 
     124       
     125    def clean_affiliation(self): 
     126      value = self.cleaned_data['affiliation'] 
     127      try: 
     128        validations.validate_affiliation(value) 
     129      except ValidationError, err: 
     130        raise forms.ValidationError, str(err) 
     131      return value 
     132       
     133    def clean_email(self): 
     134      value = self.cleaned_data['email'] 
     135      try: 
     136        validations.validate_email(value) 
     137      except ValidationError, err: 
     138        raise forms.ValidationError, str(err) 
     139      return value 
     140     
     141  return EditUserForm() 
     142 
     143 
     144 
     145 
     146 
     147class EditUserPasswordForm(forms.ModelForm): 
     148  password1 = forms.CharField(label=("Password"), required=False, widget=forms.PasswordInput) 
     149  password2 = forms.CharField(label=("Password confirmation"), required=False, widget=forms.PasswordInput, help_text = ("Enter the same password as above, for verification.")) 
     150  class Meta: 
     151    model = GeniUser 
     152    fields = ('password1','password2') 
     153     
     154  def clean(self): 
     155    data = self.cleaned_data 
     156    if data['password1'] != data['password2']: 
     157      raise forms.ValidationError(("The two password fields didn't match.")) 
     158    try: 
     159      validations.validate_password(data['password1']) 
     160    except ValidationError, err: 
     161      raise forms.ValidationError, str(err) 
     162    return data 
     163     
     164     
     165     
     166     
     167     
    94168def gen_get_form(geni_user, req_post=None): 
    95169  """ 
  • seattle/trunk/seattlegeni/website/html/media/css/profile.css

    r4340 r5611  
    44*******************************/ 
    55 
    6 table.profile { 
    7     border-collapse: collapse; 
    8         border-spacing: 0; 
    9         width: 70%; 
     6h1 {  /* ADDED July 27, 2012 */ 
     7  font-size: 1.8em;  
     8  border-bottom: 1px solid #bbb;  
     9  width: 70%; min-width: 688px; 
     10} 
     11 
     12table.profile {   
     13  border-collapse: collapse; 
     14  border-spacing: 0; 
     15  width: 70%; 
     16    min-width: 688px; /* ADDED July 27, 2012 to fix the table collapsing on itself when the browser is below a certain size */ 
    1017} 
    1118 
    1219#info { 
    13     background-color : #ded; 
    14     border : 1px solid #0a0; 
    15     padding : 1em; 
    16     margin-bottom : 1em; 
     20  background-color : #ded; 
     21  border : 1px solid #0a0; 
     22  padding : 1em; 
     23  margin-bottom : 1em; 
    1724} 
    1825 
    1926table.profile tr td.key { 
    20     text-align: right; 
    21     height: 30px; 
    22     width: 150px; 
    23     font-weight: bold; 
     27  text-align: right; 
     28  height: 30px; 
     29  font-weight: bold; 
     30    min-width: 150px; /* CHANGED July 27, 2012 (Prev. width 150px)*/ 
    2431} 
    2532 
    2633table.profile tr td.value { 
    27     padding-left: 15px;    
     34  padding-left: 15px;    
     35    min-width: 500px; /* ADDED July 27, 2012 */ 
     36} 
     37 
     38table.profile button {  
     39  width: 80px; 
     40  vertical-align: middle; 
     41  float: right; 
     42  margin-right: 15px; 
     43} 
     44 
     45table.profile span.hide_this{  
     46        display: inline; 
     47        display: none; 
     48} 
     49 
     50table.profile form{  
     51        display: inline; 
    2852} 
    2953 
    3054#download { 
    31     float: right; 
    32     border: 2px solid #666; 
    33     background-color: #fff; 
    34     padding: 10px; 
    35     margin-right: 0px; 
    36     text-align: center; 
    37     font-weight: bold; 
     55  float: right; 
     56  border: 2px solid #666; 
     57  background-color: #fff; 
     58  padding: 10px; 
     59  margin-right: 0px; 
     60  text-align: center; 
     61  font-weight: bold; 
    3862} 
    3963 
    4064#download a img { 
    41     display: block; 
    42     width: 150px; 
     65  display: block; 
     66  width: 150px; 
    4367} 
    4468 
     
    4872 
    4973#download_pubkey_form { 
    50     display : inline;    
     74  display : inline;      
    5175} 
  • seattle/trunk/seattlegeni/website/html/templates/control/profile.html

    r5259 r5611  
    55<link href="{{ MEDIA_URL }}css/profile.css" rel="stylesheet" type="text/css" /> 
    66{% endblock style %} 
     7 
     8{% block script %} 
     9{{ block.super }} 
     10<script type="text/javascript" src="{{ MEDIA_URL }}scripts/edit_profile.js" charset="utf-8"></script> 
     11{% endblock script %} 
    712 
    813{% block title %} 
     
    1722        <div id="main"> 
    1823                <div id="middle"> 
    19                          
     24                 
    2025                        <div id="download"> 
    21                                 <a href="http://seattlegeni.cs.washington.edu/dist/demokit.zip"><img src="{{ MEDIA_URL }}images/download_demokit.jpg" alt="Download demokit" />Download demokit</a> 
     26                                <a href="http://seattlegeni.cs.washington.edu/dist/demokit.zip"><img src="{{ MEDIA_URL }}images/download_demokit.jpg" alt="Download demokit"/>Download demokit</a> 
    2227                        </div> 
    2328                         
    24                         <table class="profile"> 
    25                           {% if info %} 
    26                           <tr class="even"> 
    27                             <td colspan="2"> 
    28                               <div id="info">{{ info }}</div> 
    29                             </td> 
    30                           </tr> 
    31                           {% endif %} 
    32                                 <tr class="odd"> 
     29                   <table class="profile">           
     30                                {% if info or msg %} 
     31                                <tr class="even"> 
     32                                        <td colspan="2"> 
     33                                                <div id="info">{{ info }} {{ msg }}</div> 
     34                                        </td> 
     35                                </tr> 
     36                                {% endif %} 
     37                                {% if password_form.non_field_errors or email_form.errors or affiliation_form.errors %} 
     38                                <tr class="even"> 
     39                                        <td colspan="2"> 
     40                                                <div class="warning"> 
     41                                                        {{ password_form.non_field_errors }} 
     42                                                        {{ email_form.email.errors }} 
     43                                                        {{ affiliation_form.affiliation.errors }} 
     44                                                </div> 
     45                                        </td> 
     46                                </tr> 
     47                                {% endif %} 
     48                            <tr class="odd"> 
    3349                                        <td class="key">Username</td> 
    3450                                        <td class="value">{{ username }}</td> 
     51                            </tr> 
     52                            <tr class="even"> 
     53                                        <td class="key">Password</td> 
     54                                        <td class="value"> 
     55                                                <span class="value">********</span> 
     56                                                <span class="hide_this"> 
     57                                                        <form action="{% url profile %}" method="POST"> 
     58                                                                1. {{ password_form.password1 }} <br/> 
     59                                                                2. {{ password_form.password2 }} 
     60                                                                <input type="submit" value="Save"/> 
     61                                                        </form> 
     62                                                </span> 
     63                                                <button class="edit" type="button" title="Password">Edit</button> 
     64                                        </td> 
     65                            </tr> 
     66                            <tr class="odd"> 
     67                                        <td class="key">Affiliation</td> 
     68                                        <td class="value"> 
     69                                                <span class="value">{{ affiliation }}</span> 
     70                                                <span class="hide_this"> 
     71                                                        <form  action="{% url profile %}" method="POST"> 
     72                                                                {{ affiliation_form.affiliation }} 
     73                                                                <input type="submit" value="Save"/> 
     74                                                        </form> 
     75                                                </span> 
     76                                                <button class="edit" type="button" title="Affiliation">Edit</button> 
     77                                        </td> 
    3578                                </tr> 
    3679                                <tr class="even"> 
    37                                         <td class="key">Affiliation</td> 
    38                                         <td class="value">{{ affiliation }}</td> 
     80                                        <td class="key">E-mail Address</td> 
     81                                        <td class="value"> 
     82                                                <span class="value">{{ email }} </span> 
     83                                                <span class="hide_this"> 
     84                                                        <form action="{% url profile %}" method="POST"> 
     85                                                                {{ email_form.email }} 
     86                                                                <input type="submit" value="Save"/> 
     87                                                        </form> 
     88                                                </span> 
     89                                                <button class="edit" type="button"title="E-mail">Edit</button> 
     90                                        </td> 
    3991                                </tr> 
    4092                                <tr class="odd"> 
    41                                         <td class="key">E-mail Address</td> 
    42                                         <td class="value">{{ email }}</td> 
    43                                 </tr> 
    44                                 <tr class="even"> 
    4593                                        <td class="key">Port</td> 
    4694                                        <td class="value">{{ port }}</td> 
    4795                                </tr> 
    48                                 <tr class="odd"> 
     96                                <tr class="even"> 
    4997                                        <td class="key">API Key</td> 
    5098                                        <td class="value"><a href="{% url api_info %}">View or change your API key</a></td> 
    5199                                </tr> 
    52                                 <tr class="even"> 
     100                                <tr class="odd"> 
    53101                                        <td class="key">Public Key</td> 
    54102                                        <td class="value"> 
    55                                           <form method="POST" action="{% url pub_key %}" id="download_pubkey_form">  
    56                                                 <input type="submit" value="Download" /> 
    57                                           </form> 
    58                                           <a href="{% url change_key %}">Generate or upload a new key</a> 
     103                                                <form method="POST" action="{% url pub_key %}" id="download_pubkey_form"> 
     104                                                        <input type="submit" value="Download"/> 
     105                                                </form> 
     106                                                <a href="{% url change_key %}">Generate or upload a new key</a> 
    59107                                        </td> 
    60108                                </tr> 
    61109                                {% if has_privkey %} 
     110                                <tr class="even"> 
     111                                        <td class="key">Private Key</td> 
     112                                        <td class="value"><a href="#"/> 
     113                                                <form class="inline" method="POST" action="{% url priv_key %}"> 
     114                                                        <input type="submit" value="Download"/> 
     115                                                </form> 
     116                                        </td> 
     117                                </tr> 
    62118                                <tr class="odd"> 
    63                                   <td class="key">Private Key</td> 
    64                                   <td class="value"><a href="#"> 
    65                                       <form class="inline" method="POST" action="{% url priv_key %}">  
    66                                         <input type="submit" value="Download" /></p> 
    67                                     </form> 
    68                                   </td> 
     119                                        <td class="key">Delete your private key</td> 
     120                                        <td class="value"> 
     121                                                <form class="inline" method="POST" action="{% url del_priv %}"> 
     122                                                        <input type="hidden" name="keyToDelete" value={{ username }}> </input> 
     123                                                        <input id="delete" type="submit" value="Delete"> </input> 
     124                                                </form> 
     125                                        </td> 
    69126                                </tr> 
    70127                                <tr class="even"> 
    71                                   <td class="key">Delete your private key</td> 
    72                                   <td class="value"> 
    73                                     <form class="inline" method="POST" action="{% url del_priv %}">  
    74                                       <input type="hidden" name="keyToDelete" value={{ username }}> </input> 
    75                                       <input id="delete" type="submit" value="Delete"> </input> 
    76                                     </form> 
    77                                   </td> 
    78                                 </tr> 
    79                                 <tr class="odd"> 
    80128                                        <td colspan="2"> 
    81                                             <p class="warning"> For better 
    82                                               security we recommend that you 
    83                                               download and delete your 
    84                                               private key from the 
    85                                               server. Always store your 
    86                                               private key in a secure 
    87                                               location.</p> 
     129                                                <p class="warning"> For better 
     130                                                security we recommend that you 
     131                                                download and delete your  
     132                                                private key from the  
     133                                                server. Always store your  
     134                                                private key in a secure  
     135                                                location. </p> 
    88136                                        </td> 
    89137                                </tr> 
     
    92140                </div> 
    93141        </div> 
    94  
     142         
    95143{% endblock content %} 
    96144 
  • seattle/trunk/seattlegeni/website/html/views.py

    r5494 r5611  
    110110    This method requires the request to represent a valid logged 
    111111    in user. See the top-level comment about the @login_required() 
    112     decorator to achieve this property. 
     112    decorator to achieve this property.  User account is editable through this  
     113    method. 
    113114  <Arguments> 
    114115    request: 
     
    127128  except LoggedInButFailedGetGeniUserError: 
    128129    return _show_failed_get_geniuser_page(request) 
     130  msg = '' 
     131  email_form = forms.gen_edit_user_form(instance=user) 
     132  affiliation_form = forms.gen_edit_user_form(instance=user) 
     133  password_form = forms.EditUserPasswordForm() 
     134     
     135  if request.method == 'POST': 
     136    if 'affiliation' in request.POST: 
     137       affiliation_form = forms.gen_edit_user_form(('affiliation',), request.POST, instance=user) 
     138       if affiliation_form.is_valid(): 
     139         new_affiliation = affiliation_form.cleaned_data['affiliation'] 
     140         interface.change_user_affiliation(user, new_affiliation) 
     141         msg ="Affiliation has been successfully changed to %s." % (user.affiliation) 
     142    elif 'email' in request.POST: 
     143       email_form = forms.gen_edit_user_form(('email',), request.POST, instance=user) 
     144       if email_form.is_valid(): 
     145         new_email = email_form.cleaned_data['email'] 
     146         interface.change_user_email(user, new_email) 
     147         msg ="Email has been successfully changed to %s." % (user.email) 
     148    elif 'password1' in request.POST: 
     149       password_form = forms.EditUserPasswordForm( request.POST, instance=user) 
     150       if password_form.is_valid(): 
     151         new_password = password_form.cleaned_data['password1'] 
     152         interface.change_user_password(user, new_password) 
     153         msg ="Password has been successfully changed" 
    129154   
    130155  username = user.username 
     
    133158  port = user.usable_vessel_port 
    134159  has_privkey = user.user_privkey != None 
     160  #currently not used, needed if editing user port is allowed 
     161  #port_range = interface.get_useable_ports() 
     162  #port_range_min = port_range[0] 
     163  #port_range_max = port_range[-1] 
    135164   
    136165  return direct_to_template(request, 'control/profile.html', 
    137                             {'username' : username, 
     166                            {'email_form' : email_form, 
     167                             'affiliation_form' : affiliation_form, 
     168                             'password_form' : password_form, 
     169                             'username' : username, 
    138170                             'affiliation' : affiliation, 
    139171                             'email' : email, 
    140172                             'port' : port, 
     173                             'api_key' : user.api_key, 
    141174                             'has_privkey' : has_privkey, 
     175                             #'port_range_min' : port_range_min, 
     176                             #'port_range_max' : port_range_max, 
     177                             'msg' : msg, 
    142178                             'info' : info}) 
    143179 
     
    253289  else: 
    254290    return HttpResponseRedirect(reverse("profile")) 
    255    
     291 
    256292  ltemplate = 'accounts/login.html' 
    257293  if request.method == 'POST': 
     
    274310     
    275311    return HttpResponseRedirect(reverse("profile")) 
    276        
     312     
    277313  # request type is GET, show a fresh login page 
    278314  return _show_login(request, ltemplate, {})