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;