5.8. Administration (admin.rsl)

module Admin;
from Data import TutorialDB, PageDB;
export all;


operation Login
    inputs: s:Server, uid:UserId, password:Password;
    outputs: tdb:TutorialDB and pdb:PageDB;
    precondition: exists (u in s.users) (u.id = uid) and (u.password = password);
    postcondition: tdb = s.tdb and pdb = s.pdb;
    description: (*
        Login to the given server to access its tutorial and page database.  
        If the user name and password exist on the server's user list, then return the 
        two databases database, otherwise nil.
    *);
end Login;

object Server is 
	  components:  users:Accounts and pdb:PageDB and tdb:TutorialDB;
    description: (*
        A server has a list of authentic users and tutorial/page databases.
    *);
end Server;


(*******************************)



object Accounts is
    components: UserAccount*;
    description: (*
        Accounts is the repository of registered user information.  It is a
        collection of UserAccounts.
    *);
  end Accounts;
  
  

  object UserAccount is
    components: id:UserId and password:Password and fname:FirstName and lname:LastName;
    description: (*
        A UserAccount is the information about a particular registered user.
        The First and Last Name components are the user's real-world firs and lasts names.
        The UserId is the unique identifier by which the user is known to CSTutor.
    *);
  end UserAccount;
  
  

  object FirstName is string
  	 description: (* The first name of the user. *);
  end FirstName;
  
  object LastName is string
  description: (* The last name of the user. *);
  end LastName;
  
  object UserId is string
  description: (* The ID  of the user. *);
  end UserId;
  
  object Password is string
     description: (* The user's password. *);
  end Password;
  
    operation AddUser is
    inputs: udb:Accounts, ur:UserAccount;
    outputs: udb':Accounts;
    description: (*
        Add the given UserAccount to the given Accounts.  The UserId of the given
        user record is required and must not be the same as a user record already in the
        Accounts.  The First and Last Name compenets are not required.
    *);

    precondition:
        (*
         * There is no user account in the input Accounts with the same id as the
         * record to be added.
         *)
        (not (exists (ur' in udb) ur'.id = ur.id))

            and

        (*
         * The id of the given user record is not empty.
         *)
        (ur.id != nil);

    postcondition:
        (*
         * A user record is in the output db if and only if it is the new
         * record to be added or it is in the input db.
         *)
        forall (ur':UserAccount)
            (ur' in udb') iff ((ur' = ur) or (ur' in udb));

  end AddUser;

  operation FindUser is
    inputs: udb:Accounts, id:UserId;
    outputs: ur':UserAccount;
    description: (*
        Find a user account by unique id.
    *);

    precondition: ;

    postcondition:
        (*
         * If there is a record with the given id in the input db, then the
         * output record is equal to that record, otherwise the output record
         * is empty.
         *)
        (exists (ur in udb) (ur.id = id) and (ur' = ur))
            or
        (not (exists (ur in udb) (ur.id = id)) and (ur' = nil));

  end FindUser;

  operation FindUser is
    inputs: udb:Accounts, fname:FirstName, lname:LastName;
    outputs: url:UserAccount*;
    description: (*
        Find a user or users by first and last name.  If more than one is found,
        the output list is sorted by id.
    *);

    precondition: ;

    postcondition:
        (*
         * The output list consists of all records of the given name in the
         * input db.
         *)
        (forall (ur' in url) (ur' in udb) and (ur'.lname = lname) and (ur'.fname = fname))

            and

        (*
         * The output list is sorted alphabetically by id.
         *)
        (forall (i:integer | (i >= 1) and (i < #url))
            url[i].id < url[i+1].id);

  end FindUser;

 

  operation ChangeUser is
    inputs: udb:Accounts, old_ur:UserAccount, new_ur:UserAccount;
    outputs:  udb':Accounts;
    description: (*
        Change the given old UserAccount to the given new record.  The old and
        new records must not be the same.  The old record must already be in
        the input db.  The new record must meet the same conditions as for the
        input to the AddUser operation.  Typically the user runs the FindUser
        operation prior to Change to locate an existing record to be changed.
    *);

    precondition:
        (*
         * The old and new user records are not the same.
         *)
        (old_ur != new_ur)

            and

        (*
         * The old record is in the given db.
         *)
        (old_ur in udb)

            and

        (*
         * There is no user record in the input Accounts with the same id as the
         * new record to be added.
         *)
        (not (exists (new_ur' in udb) new_ur'.id = new_ur.id))

            and

        (*
         * The id of the new record is not empty and 8 characters or less.
         *)
        (new_ur.id != nil);

          
    postcondition:
        (*
         * A user record is in the output db if and only if it is the new
         * record to be added or it is in the input db, and it is not the old
         * record.
         *)
        forall (ur':UserAccount)
            (ur' in udb') iff (((ur' = new_ur) or (ur' in udb)) and
                                   (ur' != old_ur));


  end ChangeUser;

  operation DeleteUser is
    inputs: udb:Accounts,  ur:UserAccount;
    outputs: udb':Accounts;
    description: (*
        Delete the given user account from the given Accounts.  The given record
        must already be in the input db.  Typically the user runs the FindUser
        operation prior to Delete to locate an existing record to delete.
    *);

    precondition:
        (*
         * The given UserAccount is in the given Accounts.
         *)
        ur in udb;

    postcondition:
        (*
         * A user record is in the output db if and only if it is not the
         * existing record to be deleted and it is in the input db.
         *)
        (forall (ur':UserAccount)
            (ur' in udb') iff ((ur' != ur) and (ur' in udb)));

         
  end DeleteUser;
  
  
  end Admin;