Account API
This is the documentation for the Python client for the MaIS Account API.
Everything on this page is located in the stanford.mais.account module.
To begin using the MaIS Account API, you should first instantiate a
MAISClient object. Once that is done, you can
use it to instantiate an stanford.mais.account.AccountClient.
Note
All Account instances are read-only. You cannot use this SDK to create or change accounts.
Account API Client
You will use the AccountClient instance to
access the Account API. Instantiating a
AccountClient is easy:
client = MAISClient(...)
wclient = AccountClient(client)
For performance, the AccountClient
maintains a cache of fetched accounts. To clear the cache, call
clear_cache().
Warning
Once you clear the cache, avoid using any Account instances that you might have used before!
Fetching Accounts
Once you have a AccountClient, there are
several ways you can access accounts. The accounts you access will be
instances of the Account class.
One way is to use the get() method
to fetch an accounts, providing the username of the accounts that you want.
Important
Usernames are all lowercase.
The
AccountClient also implements the
__getitem__ method, so instead of calling
get() you can get accounts as
you would items from a dict.
Here is an example of the two ways you can get a account:
aclient = AccountClient(...)
# These two operations give you the same Workgroup:
lelandjr = aclient.get('lelandjr')
lelandjr = aclient['lelandjr']
Account Views
Stanford accounts represent more than just people. “Functional Accounts” exist
for services that need to act as an account. Most applications only care about
people, so Account Views may be used to limit an
AccountClient to just the types of accounts
that you want.
An Account View is enabled by calling the appropriate
AccountClient method. There are four Account
Views available:
only_active(): Limits fetching and existance tests to only active accounts.only_inactive(): Limits fetching and existance tests to only inactive accounts.only_people(): Limits fetching and existance tests to only accounts for people.only_functional(): Limits fetching and existance tests to only functional accounts.
Each method returns a modified AccountClient,
whose get(), __getitem__, and
__contains__ methods will only ‘see’ accounts matching the view you
requested. If you try to call get()
for an account that does not match the view you requested, a KeyError
will be raised.
Tip
Account Views can be chained together!
See the following example of Account Views in action:
# `lelandjr` is an inactive person account;
# `functional` is an active functional account.
aclient = AccountClient(...)
'lelandjr' in aclient # True
'functional' in aclient # True
# Make an Account View limited to people:
aclient_people = aclient.only_people()
'lelandjr' in aclient_people # True
'functional' in aclient_people # False
# Account Views can be 'chained' together:
aclient_active_people = aclient.only_people().only_active()
'lelandjr' in aclient_active_people # False
'functional' in aclient_active_people # False
# To an Account View, non-matching accounts do not exist:
lelandjr1 = aclient['lelandjr'] # works fine
lelandjr2 = aclient_active_people['lelandjr'] # KeyError
Searching for Accounts
The Account API provides limited support for searching for accounts. You are only able to check if an account exists, and you are only able to search for accounts that have recently changed status.
Account Existence
Instances of AccountClient implement
Container functionality, so you can check for account
existence like so:
aclient = AccountClient(...)
lelandjr_exists = (True if 'lelandjr' in aclient else False)
Warning
This check respects any Account Views you have in place. If you do an in
check on an Account View, you might get False even if the account
actually exists!
Accounts who Changed Status
The Account API provides a way to search for accounts which have recently
changed status (where “recently” means “from 1 to 30 days ago”). You can
perform this search by calling the
get_changed_status() method.
The method takes three parameters:
days: How far back to search, from 1 to 30.current_status: One ofactive,inactive, orpending, only accounts with this current status will be included in the results.Note
pendingis a status that accounts take when they are first created, and are not yet active.Important
This search only counts the current status. If an account has changed from active to inactive and back to active in the last 3 days, a search with
days=5andcurrent_status='inactive'will not include that account; the account had gone inactive within the search period, but it is not inactive now.get_people: If True, only accounts for people are returned; if False, only functional accounts are returned.
The result of the search is a set, so if you need to run the search
multiple times, you can combine results using unions.
This search returns “lite” account records, not full account records. These
records are represented by the PartialAccount
class, which contains the following properties:
sunetid: The account’s username.is_person: True if the account is for a person; False otherwise.is_active: True if the account is active; False otherwise.last_update: The last time the account was updated, as an awaredatetime.
If you need the full Account, you can fetch it
by calling the account() method.
For example, here is code that runs a search and outputs a list of usernames (which are included in lite account records) and names (which are not):
aclient = AccountClient(...)
results1 = aclient.get_changed_status(
days=7,
current_status='active',
get_people=True
)
results2 = aclient.get_changed_status(
days=7,
current_status='active',
get_people=False,
)
print("New accounts in the last 7 days:")
for result in (results1 | results2):
account = result.account(aclient)
print(f"* {result.sunetid} ({account.name})")
SUNetID Validation
If you have a collection of SUNetIDs, and you want to confirm that they are all
SUNetIDs, you can use the validation function
stanford.mais.account.validate.validate(), which is in the
stanford.mais.account.validate module.
The function takes two parameters:
Either a string, or a collection — a
list,tuple,set, orfrozenset— of strings. If you provide a string, items in the string must be separated by whitespace.An
AccountClient.Warning
If you provide an Account View, validation will take that into account, and may provide unexpected results!
validate() returns an
AccountValidationResults, with
usernames sorted into four properties:
full: The SUNetIDs of active, full-service (or full-sponsored) accounts.base: The SUNetIDs of active, base-service (or base-sponsored) accounts.inactive: The SUNetIDs of inactive accounts.unknown: Usernames that are either functional accounts, or that are not accounts.
Each property is a collection of strings, where each string is a SUNetID
(except for
unknown, where
the strings might be functional account usernames).
Account Class
The Account class represents “full” account
records. They are obtained by using
get(), or when upgrading a
PartialAccount “lite” account record using
account().
Properties
Every Account has properties, all of which are
read-only.
Note
This section provides summaries only. See the Module Documentation for details about each property!
sunetid: The account’s username. For accounts for people, this is a SUNetID.name: The account’s name.description: For people, this is some combination of their Org name and position title; for functional accounts, this is a description set at the time of the account’s creation.is_person: If True, this is an account for a person; False otherwise.is_active: If True, this account is active and may use Stanford services.Important
Frozen person accounts are still considered active.
last_update: Thedatetimewhen the account (not theAccountinstance, the actual underlying account) was last changed.
Account Services
In this context, a “service” represents a core University service that is made
available to an account. For example, active accounts for people always have a
kerberos service, while active functional accounts for the Shared Email
service all have a seas service.
Services may have “settings” associated with them, which are key-value pairs. Keys may be optional, and may be multi-valued.
Note
When a service is not active, all service-specific settings become optional.
Warning
When a service is inactive, not only do all service-specific settings become optional, but some services may have settings un-set when they go inactive.
To access the services for an account, obtain a
Account instance for the account, and access
the services property.
The services
property is a AccountServiceTypes,
which itself contains one property for every service. If an account has the
service, the property will contain something; if the account does not have the
service, the property will be None.
Important
Just because a service does not exist for an account, does not mean that it never existed for an account.
Here is an example of how to look up an account’s UNIX User ID (UID) number.
If the account does not have the kerberos service, or the service is not
active, then None is returned:
def get_uid(
account: Account,
) -> int | None:
if account.services.kerberos is None:
return None
elif account.services.kerberos.is_active is False:
return None
else:
return account.services.kerberos.uid
Each service has its own class, subclasses of
AccountService. This class, and its
subclasses, exist in the stanford.mais.account.service module.
Service Status
Every service contains a status property, which will return a
ServiceStatus. There are three
possible statuses:
active: The service is active for the account.
frozen: The account has the service, but may not use it at this time.
inactive: This account does not have this service.
The is_active property
will tell you if a service is active.
Warning
Because of the existence of the frozen status, it is not safe to
assume that if
is_active is False,
that the service is inactive.
Instead, consider using
not_inactive.
Popular Services
These are the services you will most likely care about.
Note
This section provides summaries only. See the Module Documentation for details about each service!
Kerberos
AccountServiceTypes property name: kerberosAccountServiceKerberosAll active accounts for people will have this service. Functional accounts for CGI will also have this service.
The service has two settings, both required, and both single-valued:
principal: The name of the user’s Kerberos principal. This is normally the same as their SUNetID, and is not scoped.uid: The account’s UNIX UID number.
This is the only account which may
SEAS
AccountServiceTypes property name: seasAccountServiceSEASThe “Stanford Electronic Alias Service”, this represents an active @stanford.edu email address for the account. People who have this service have a full account (sponsored or not). Functional accounts for shared email also have this service.
The service has seven settings, which are single-valued unless noted:
Warning
Many of these settings contain email addresses. Unless noted, do not send email to them without authorization.
sunetid: Required, multi-valued. One of the entries in the list will be the account’s username (for people, the person’s SUNetID). Additional entries in this list are aliases, at which the user may also receive mail.sunetidpreferred: Required. This will be one of the entries from thesunetidlist, and is the identifier (after concatenating with@stanford.edu) at which the account wishes to receive email.Note
It is OK to send emails to this address.
forward: Optional. Single-valued, with multiple emails separated by a comma. If present, emails received by this account will be forwarded to the email addresses contained herein.local: Optional. The canonical, fully-qualified email address for the account’s Stanford email box.emailsystem: Optional. The identifier of the service which hosts said mailbox.urirouteto: Required. When someone browses tohttps://stanford.edu/~username, they will be directed to the URI contained herein. If an empty string, the account has no associated URI. If a relative URI, it is relative tohttps://web.stanford.edu/.
Other Services
These are services which will be of interest to specific groups of developers.
Note
This section provides summaries only. See the Module Documentation for details about each service!
Email
AccountServiceTypes property name: emailAccountServiceEmailIf active, the account has a Stanford personal electronic mailbox. The
seas service should also be active.
All this service’s settings are obsolete, and should not be used.
Leland
AccountServiceTypes property name: lelandAccountServiceLelandOriginally created for Stanford’s Shared Computing environment, today it represents access to FarmShare.
All active full-service (and full-sponsored) accounts for people will have this service. This service is another way to tell if a person has a base or full account.
The service has one required, single-valued setting:
shell: The absolute path to the user’s shell.
PTS
AccountServiceTypes property name: ptsAccountServicePTSThis represents the accounts entry in the AFS ir cell’s Protection Server.
People and CGI functional accounts will have this service. This is required
for the account to access any AFS service at Stanford.
The service has one required, single-value setting:
uid: The UID number for the account. It should be the same as the account’s UID number in the kerberos service.
AFS
AccountServiceTypes property name: afsAccountServiceAFSThis represents an account’s AFS home volume. CGI functional accounts might also have this service.
The service has one required, single-value setting:
homedirectory: The absolute path to the account’s AFS home directory in theircell.
Library
AccountServiceTypes property name: libraryAccountServiceLibraryThis represents access to library e-resources, which full-service accounts receive automatically, and which sponsored accounts may have granted to them.
The service has no settings.
Obsolete Services
Two services are obsolete. Accounts might still have one or more of these services; they are listed here, and documented in Module Documentation.
autoreply:AccountServiceAutoreplydialin:AccountServiceDialin
Module Documentation
stanford.mais.account
This module contains the AccountClient, used to
access the Account API.
- class stanford.mais.account.AccountClient(client: ~stanford.mais.client.MAISClient, _cache: ~collections.abc.MutableMapping[str, ~stanford.mais.account.account.Account] = <factory>, _filters: frozenset[~collections.abc.Callable[[~stanford.mais.account.account.Account], bool]] = <factory>)[source]
The
AccountClientis the second thing you will instantiate when you want to interact with the MaIS Account API. (The first thing you instantiate is aMAISClient). Once you have aMAISClient, you pass it to theAccountClientconstructor with this parameter:- Parameters:
client (stanford.mais.client.MAISClient) – The MAIS client to use.
Once you have an
AccountClientinstantiated, you can useget()to fetch an account. For your convenience, instances of this class also implement__getitem__, so instead of doing…aclient = AccountClient(...) lelandjr = client.get('lelandjr')
… you can do …
aclient = AccountClient(...) lelandjr = client['lelandjr']
Instances also implement
Containerfunctionality, so you can check for account existence like so:aclient = AccountClient(...) lelandjr_exists = (True if 'lelandjr' in aclient else False)
Through the use of caching, if you then decide to fetch the account after confirming its existance, the entry will be served from cache instead of making a fresh API request.
Warning
The existence of an account does not mean it is active!
- client: MAISClient
A
MAISClientinstance.This configures the API endpoint (accessed via
client.urls['account']) and client key/cert to use. It must be provided when calling the class constructor.- Raises:
TypeError – A client was not provided.
- get(sunetid: str) Account[source]
Fetch an Account.
This is a convenience wrapper around
Account.get(). All other parameters provided are passed through toget(), and the resulting instance is returned.Refer to
Account.get()for details on parameters, exceptions, etc..
- clear_cache() None[source]
Clear cache of accounts.
As mentioned in the class docs, visited accounts are cached locally, for speed and to reduce load on the Account API. Although accounts rarely change, in long-running programs, this can be a problem. To assist, this method clears the cache of this specific Account client.
Danger
If you are holding a reference to an existing
Account, or to one of the the Account’s services, clearing the cache does not invalidate those references!This method should not be called unless you know what you are doing.
- only_active() AccountClient[source]
Create a modified
AccountClientthat can only see active accounts.The returned client instance has been modified so that
get()only returns active accounts. If you try to look up an inactive account,get()will act as if the account does not exist.As many Account API consumers are only interested in active accounts, you may find this to be very convenient. If this interests you, you can do something like this:
import stanford.mais.client from stanford.mais.client.account import AccountClient api_client = stanford.mais.client.MAISClient(...) active_accounts = AccountClient(api_client).only_active()
Tip
You can stack these filters. For example,
AccountClient(api_client).only_active().only_people()will only be able to “see” active people accounts (ignoring active functional accounts).Warning
The ‘client’ returned by this method uses the same caches as this client. Therefore, it must not be used across threads/processes.
- only_inactive() AccountClient[source]
Create a modified
AccountClientthat can only see inactive accounts.The returned client instance has been modified so that
get()only returns inactive accounts. If you try to look up an active account,get()will act as if the account does not exist.See
only_active()for examples, tips, and warnings.
- only_people() AccountClient[source]
Create a modified
AccountClientthat can only see accounts of people.The returned client instance has been modified so that
get()only returns the accounts of people. If you try to look up a functional account,get()will act as if the account does not exist.As many Account API consumers are only interested in SUNetIDs, you may find this to be very convenient. If this interests you, you can do something like this:
import stanford.mais.client from stanford.mais.client.account import AccountClient api_client = stanford.mais.client.MAISClient(...) sunetids = AccountClient(api_client).only_people()
And, if you only care about active SUNetIDs, you can chain them together, like this:
import stanford.mais.client from stanford.mais.client.account import AccountClient api_client = stanford.mais.client.MAISClient(...) active_sunetids = AccountClient(api_client).only_active().only_people()
Warning
The ‘client’ returned by this method uses the same caches as this client. Therefore, it must not be used across threads/processes.
- only_functional() AccountClient[source]
Create a modified
AccountClientthat can only see functional accounts.The returned client instance has been modified so that
get()only returns functional accounts. If you try to look up a person’s account (a SUNetID),get()will act as if the account does not exist.See
only_people()for examples, tips, and warnings.
- get_changed_status(days: int, current_status: Literal['active', 'inactive', 'pending'], get_people: bool = True) frozenset[PartialAccount][source]
Search for accounts which have recently changed status.
Search for all accounts that have changed status within the specified number of days. This is commonly used to get a list of accounts that have changed status
Warning
This call only includes accounts which have changed status. Changes to other attributes—like a person’s name, or a service setting like email aliases—will not cause an account to be included in these results.
Warning
The search results will tell you which accounts changed status, but they will not tell you the old status.
Note
This method is not affected by the modified AccountClient instances returned by
only_active(),only_inactive(),only_people(), andonly_functional().- Parameters:
days – Include accounts that changed status within this many days. Must be at least 1, and at most 30.
current_status –
Only accounts with this current status will be included in the results.
The status pending refers to an account which has just been created and is not yet active. It is only used at the very beginning of an account’s life cycle.
Note
Only one current_status value may be provided. If you want a list of all accounts which have changed status, run this search multiple times (once for each status), and perform a set union on the results.
Warning
It is possible for an account to change status multiple times during your search period. For example, if you search for current_status
active, your search results might include accounts which were already active, went inactive, and then became active again.get_people –
If True (which is the defaut), only accounts for people will be included in the results. If you instead want results for functional accounts, change this to
False.Note
The search can return either people accounts or functional accounts, not both. If you want both, then make two searches and perform a set union on the results.
- Raises:
ValueError – You provided an invalid days.
PermissionError – You did not use a valid certificate, or do not have permissions to perform the operation.
NotImplementedError – An unexpected HTTP response was received.
requests.Timeout – The MaIS Workgroup API did not respond in time.
When searching for accounts which have changed status recently, the results
returned are instances of PartialAccount,
representing “lite” account records.
- class stanford.mais.account.PartialAccount(sunetid: str, is_person: bool, is_active: bool, last_update: datetime)[source]
Part of a Stanford Account.
This is a “lite” account record. Lite accounts are returned by the Workgroup API in two cases:
When you fetch a lite account, instead of a full account (we never do this).
When you request a list of accounts that have changed status recently.
The entire contents are read-only.
To get the full account, call the
account()method to getch a full account record.- sunetid: str
For people, their SUNetID is also their username. For functional accounts, this is their username. This is the
idkey from the API.Tip
This is used as the account’s
uidin LDAP.
- is_person: bool
If True, this account is for a person. If False, this account is for a “functional account”. This is the
typekey from the API.
- is_active: bool
If True, this account is active. If the account is for a person, then assuming the person’s kerberos service is not frozen or otherwise blocked, they are able to use Stanford Login. If the account is a functional account, then the associated services are active. This does not imply anything else. This is computed from the
statuskey from the API.
- last_update: datetime
The timezone-aware datetime when the account was last updated. This is computed from the
statusDateStrkey from the API.
- account(client: AccountClient) Account[source]
Fetch the full
Accountfor this search result.This is a convenience method, performing a normal account lookup and returning the result.
Warning
The returned Account may have a different is_active or last_update value. Once you call this method, you should stop using this PartialAccount.
Note
The returned Account will have the same is_person value as this partial account.
- Parameters:
client – The AccountClient to use for the lookup.
- Returns:
The full
Accountfor this PartialAccount’s SUNetID.- Raises:
ChildProcessError – Something went wrong on the server side (a 400 or 500 error was returned).
KeyError – The SUNetID changed between now and when this PartialAccount was returned in search results. This is extremely rare.
PermissionError – You did not use a valid certificate, or do not have permissions to perform the operation. This is also rare, and means you either changed certificates, or your certificate has been disabled or expired.
requests.Timeout – The MaIS Workgroup API did not respond in time.
stanford.mais.account.account
- class stanford.mais.account.Account(client: AccountClient, sunetid: str, name: str, description: str, is_person: bool, is_active: bool, is_full: bool, services: AccountServiceTypes, last_update: datetime.datetime, raw: dict[str, Any])[source]
A SUNetID Account.
The entire contents are read-only.
Note
Information from the Account API is generally mapped to attributes in the Accounts Tree in Stanford LDAP.
- client: AccountClient
The
AccountClientrepresenting the API endpoint we are using.
- sunetid: str
For people, their SUNetID is also their username. For functional accounts, this is their username. This is the
idkey from the API.Tip
This is used as the account’s
uidin LDAP.
- name: str
For people, this is ther name (last name first). For functional accounts, this is a name set at the time of account creation, followed possibly by a descriptor like “ - shared email”. This is the
namekey from the API.
- description: str
For people, this is a combination of their Org name and their position title. This may be set to “Former …” or the like for inactive accounts For functional accounts, this is a description set at the time of account’s creation. This is the
descriptionkey from the API.Tip
This is used as the account’s
descriptionin LDAP.
- is_person: bool
If True, this account is for a person. If False, this account is for a “functional account”. This is the
typekey from the API.
- is_active: bool
If True, this account is active. If the account is for a person, then assuming the person’s kerberos service is not frozen or otherwise blocked, they are able to use Stanford Login. If the account is a functional account, then the associated services are active. This does not imply anything else. This is computed from the
statuskey from the API.
- is_full: bool
If True, this is a person with a a full SUNetID. See SUNet IDs in Detail to learn what it means to have a full SUNetID. We check for full status by seeing if the SUNetID has the
lelandservice associated with it.If
is_fullis False butis_personis True, then this is a person with a base SUNetID.Warning
At this time, is it not possible to tell if the account is sponsored.
- services: AccountServiceTypes
This contains the services currently associated with the account. Each service exists as a property, mapping to a subclass of
AccountService. If an account does not have a service defined, then the property maps toNone.You can use this technique to see if an account has a service:
def has_kerberos(sunetid: Account) -> bool: if sunetid.services.kerberos is None: return False else: return sunetid.services.kerberos.is_active
Note
From time to time, new services are defined. Those services will not appear in this mapping until a software update is released, defining a new subclass for that service. If you need to access the service’s data before that time, use
raw, and look in theserviceskey for the new service.The following services are recognized, and have the following
AccountServicesubclasses:kerberos:AccountServiceKerberoslibrary:AccountServiceLibraryseas:AccountServiceSEASemail:AccountServiceEmailautoreply:AccountServiceAutoreplyleland:AccountServiceLelandpts:AccountServicePTSafs:AccountServiceAFSdialin:AccountServiceDialin
- last_update: datetime.datetime
The timezone-aware datetime when the account was last updated. is already set to the UTC timezone. This is computed from the
statusDateStrkey from the API.
- raw: dict[str, Any]
This is the parsed JSON returned from the MaIS Account API. Most keys have already been parsed, and are available as properties. Here are some additional keys you can find:
owner: This is a string with two parts, with a forward-slash used as a separator.
If the account is for a person, then this string will be
person/followed by the RegID of the person.If the account is for a functional account, then this string will be
organization/followed by the RegID of the Org which owns the functional account.
statusDate: The date when this account was last changed, in the US/Pacific time zone, in the form of a POSIX timestamp tht has been multiplied by 1,000 and microseconds added on to the end. You can parse this using
datetime.datetime.fromtimestamp()and the third-partypytz.timezoneas follows:statusDateInt=account.raw['statusDate'] statusDate=datetime.datetime.fromtimestamp( statusDateInt//(10**3), tz=pytz.timezone('US/Pacific') ).replace( microsecond=statusDateInt%(10**3) ).astimezone( pytz.utc )
Tip
You really should just use
last_update()instead.url: The MaIS Account API URL to look up this account.
- classmethod get(client: AccountClient, sunetid: str) Account[source]
Given a string, return an Account.
This uses the MaIS Workgroup API to look up information for an account, using the SUNetID (or functional account username/uid) as input.
This function is memoized; once a lookup is performed, subsequent calls for the same input will return the same result instance, thanks to the use of a cache.
Warning
This will looks up accounts of all types, both accounts for people and also functional accounts. Check
is_personbefore assuming you are working with a SUNetID. Also consider usingAccountClient.only_people().Warning
This memoization means that, should an account change status after lookup, that status change will not be noticed until after the module is reloaded. That means this code should not be used by long-running client code. Use
AccountClient.clear_cache()if necessary.- Parameters:
client – An
AccountClientrepresenting our API endpoint.sunetid – The ID to look up. This must be an actual ID, not an alias.
- Raises:
ChildProcessError – Something went wrong on the server side (a 400 or 500 error was returned).
KeyError – The given ID does not exist. Maybe it was an alias?
PermissionError – You did not use a valid certificate, or do not have permissions to perform the operation.
UnicodeEncodeError – The ID you provided included non-ASCII characters.
ValueError – The input contains non-ASCII characters.
NotImplementedError – An unexpected HTTP response was received.
requests.Timeout – The MaIS Workgroup API did not respond in time.
- class stanford.mais.account.account.AccountServiceTypes(kerberos: AccountServiceKerberos | None, library: AccountServiceLibrary | None, seas: AccountServiceSEAS | None, email: AccountServiceEmail | None, autoreply: AccountServiceAutoreply | None, leland: AccountServiceLeland | None, pts: AccountServicePTS | None, afs: AccountServiceAFS | None, dialin: AccountServiceDialin | None)[source]
The different types of services which may be attached to an Account.
Since not all services may be associated with an account, these are all marked as optional.
stanford.mais.account.service
- class stanford.mais.account.service.ServiceStatus(value)[source]
The possible statuses of a service.
- ACTIVE = 'active'
The account has and can use this service.
- FROZEN = 'frozen'
The account has this service, but it is inaccessible right now.
Note
Not every service uses this status.
- INACTIVE = 'inactive'
The account does not have this service.
Note
The account may have had the service in the past, but does not now. For example, full SUNetIDs have access to the autoreply service, but when autoreply is not enabled, the service is inactive.
- class stanford.mais.account.service.AccountService(name: str, status: ServiceStatus)[source]
The base class for all account services.
This is a base class representing a service, and stores the common properties that a service can have (the
nameof the service, and itsstatus). For service-specific properties, check out the documentation for the appropriate subclasses.- status: ServiceStatus
The service’s status.
- property is_active: bool
Trueif the service is active.Danger
This will return True only when the service is active, not when the service is frozen.
For some services, you might not care if the service is frozen. For example, if an account’s kerberos service is frozen, you might want to keep them in the directory, even if you don’t want to allow logins.
- class stanford.mais.account.service.AccountServiceKerberos(name: str, status: ServiceStatus, principal: str, uid: int)[source]
kerberosservice for an Account.This represents an account’s entry in Kerberos. If an account has this service, then the account is at least a base (or base-sponsored) account.
- class stanford.mais.account.service.AccountServiceLibrary(name: str, status: ServiceStatus)[source]
libraryservice for an Account.New as of 2019, this represents access to Library e-resources. It has no known settings, and you should not assume that having this enabled means the account is full or full-sponsored.
- class stanford.mais.account.service.AccountServiceSEAS(name: str, status: ServiceStatus, local: str | None, sunetid: list[str], sunetidpreferred: str, emailsystem: str | None, forward: str | None, urirouteto: str)[source]
seasservice for an Account.The “Stanford Electronic Alias Service”. If this service is active, then the account has an associated @stanford.edu email address, even if they don’t have a Stanford email box.
Note
Even though they include a shared mailbox, Shared Email functional accounts have
seasservice, but notemailservice.- local: str | None
This is an optional setting. If the account has a Stanford email box, and the account wants emails delivered to that mailbox, then this is the this is the canonical email address for that mailbox.
Warning
Do not try to send emails directly to this email address.
- sunetid: list[str]
This is a setting which may appear multiple times. Each entry represents an @stanford.edu email address. There will always be one entry matching the account’s ID (so that
id@stanford.eduworks). If the user has any email alises, each alias will appear as an additional entry.Danger
Do not use this to look up an account’s SUNetID/uid!
- sunetidpreferred: str
One of the entries from
sunetid, this is the alias the the person prefers others use for email comunication.Note
This setting, along with the tier-specific suffix (
@stanford.eduin PROD), is used for the user’smailattribute in LDAP (which you can find in the people tree).
- emailsystem: str | None
For accounts which have a Stanford electronic mailbox (the
emailservice, this specifies which service hosts said mailbox. Known values includeoffice365andgmail.Warning
Functional accounts (including those for Shared Email) do not have the
emailservice, and so they will not have this setting.
- forward: str | None
This is an optional setting. If present, emails received by this account will be forwarded to the emails listed in this setting. Multiple emails are separated by a comma.
Warning
Do not try to send emails directly to this email address.
- urirouteto: str
When a user points their web browser to to https://stanford.edu/~id, this is the URI where the client will be redirected. If it is just a path (not a full URL), it is relative to https://web.stanford.edu/.
- class stanford.mais.account.service.AccountServiceEmail(name: str, status: ServiceStatus, accounttype: str, quota: int | None, admin: str | None)[source]
emailservice for an Account.If active, the account has a Stanford electronic mailbox. The
seasservice should also be present and active.Note
The specific email backend (Zimbra, Office 365, Google, …) is not indicated.
- class stanford.mais.account.service.AccountServiceAutoreply(name: str, status: ServiceStatus, forward: str, subj: str, msg: str)[source]
autoreplyservice for an Account.This used to represent the email autoresponder service. If active, incoming emails would have been forwarded to the autoresponder service, which would send an appropriate reply.
In May 2025, the central autoresponder service was turned off. Autoreply is now managed within the user’s email system (Office 365, GMail, etc.). This service may disappear in the future.
- forward: str
The account’s canonical email address in the autoresponder system.
Warning
Do not try to send emails directly to this email address.
- class stanford.mais.account.service.AccountServiceLeland(name: str, status: ServiceStatus, shell: str | None)[source]
lelandservice for an Account.This represents the Stanford Shared Computing environment, once known as Leland and known today as FarmShare. If active, users are able to log in to FarmShare.
Note
Full and full-sponsored accounts have this active; base and base-sponsored account do not. Functional accounts never have this active.
- class stanford.mais.account.service.AccountServicePTS(name: str, status: ServiceStatus, uid: int)[source]
ptsservice for an Account.This represents an account’s entry in the AFS Protection Server’s database. An account must have an entry here in order to access any AFS services.
- class stanford.mais.account.service.AccountServiceAFS(name: str, status: ServiceStatus, homedirectory: str)[source]
afsservice for an Account.This represents an account’s AFS home volume.
Note
Just because someone has active AFS service, does not mean they actually have a home volume. New Faculty and Staff members must request an AFS home volume.
Tip
It is still possible to use AFS without a home volume, as long as you use a service (like FarmShare) that does not use AFS for home directories.
- homedirectory: str
The path to the account’s home directory.
Note
This is used as the account’s
homeDirectoryin LDAP. As such, you will probably want to override it.Note
This setting assumes that AFS is mounted at path
/afson a system. This is normally, but not always, the case. This setting also assumes that your system has an up-to-date copy of the CellServDB file, which should be the case if you are using a packaged OpenAFS client.
- class stanford.mais.account.service.AccountServiceDialin(name: str, status: ServiceStatus)[source]
dialinservice for an Account.This represented the Stanford UIT dial-in modem pools, which had various phone numbers, including +1 (415) 498-1440 (this was before area code 650) and +1 (650) 325-1010. If this service was active, you had access to the pool. It has no settings, and should not be used. If may disappear in the future.
stanford.mais.account.validate
This module contains the validate()
function, used to bulk-validate a collection of SUNetIDs.
- stanford.mais.account.validate.validate(raw: str, client: AccountClient) AccountValidationResults[source]
- stanford.mais.account.validate.validate(raw: list[str] | tuple[str] | set[str] | frozenset[str], client: AccountClient) AccountValidationResults
- stanford.mais.account.validate.validate(raw: list[str] | tuple[str] | set[str] | frozenset[str], client: AccountClient) AccountValidationResults
- stanford.mais.account.validate.validate(raw: list[str] | tuple[str] | set[str] | frozenset[str], client: AccountClient) AccountValidationResults
- stanford.mais.account.validate.validate(raw: list[str] | tuple[str] | set[str] | frozenset[str], client: AccountClient) AccountValidationResults
Given a list of SUNetIDs—as a
str,list,tuple,set, orfrozenset—validate and check status.This takes a list of SUNetIDs, and returns a list of SUNetIDs which have been checked against the Accounts API for both activeness and service level. The returned result shows which SUNetIDs are active full (or full-sponsored), active base (or base-sponsored), or inactive. All other entries (including those representing functional accounts) are rejected as “unknown”.
If the input is a string, then the input string may be separated by commas, and/or whitespace, (where “whitespace” is a space, newline/linefeed, form feed, carriage return, tab/horizontal tab, or vertical tab character). If the input is a list, tuple, or set; the function assumes that all whitespace etc. have been removed.
Note
“List, tuple, set, or frozenset” is used instead of the generic
Collectionbecause astris also a collection (of one-characterstr). See typing issue #256 for the discussion around this issue.This is designed to catch most exceptions. Exceptions related to validation (for example, attempting to validate an obviously-invalid SUNetID like
ab$#) will result in the ‘SUNetID’ being added to the unknown list, instead of throwing an exception. The only exceptions that should be expected from this function are ones related to API issues.- Parameters:
raw – The list of SUNetIDs. If a
str, then the list must be either comma- and/or whitespace-separated.client – An
AccountClientto connect to the Account API.
- Returns:
The results of the validation. See
AccountValidationResultsfor details.- Raises:
ChildProcessError – Something went wrong on the server side (a 400 or 500 error was returned).
PermissionError – You did not use a valid certificate, or do not have permissions to perform the operation.
requests.Timeout – The MaIS Workgroup API did not respond in time.
Validation results are returned via an instance of
AccountValidationResults.
- class stanford.mais.account.validate.AccountValidationResults(raw: str | None, raw_set: Collection[str], full: Collection[str], base: Collection[str], inactive: Collection[str], unknown: Collection[str])[source]
Results of doing an account validation.
This class contains the result of calling
validate().- raw: str | None
The raw input string provided for validation. This is only provided when a string was provided to
validate().
- raw_set: Collection[str]
The raw input provided for validation. If a string was provided to
validate(), then this is the raw input after being split. If the input tovalidate()was a set, then this is that set. Otherwise, this is the input tovalidate(), but as a set.The set union of
full,base,inactive, andunknownis equal to this.
- full: Collection[str]
The set of active full (or full-sponsored) SUNetIDs found in
raw_set.
- base: Collection[str]
The set of active base (or base-sponsored) SUNetIDs found in
raw_set.
- inactive: Collection[str]
The set of inactive SUNetIDs found in
raw_set.
- unknown: Collection[str]
The set of entries from
raw_setthat are not SUNetIDs. This includes uids that are functional accounts.