diff --git a/.gitignore b/.gitignore index 8e5f25d..e0073cf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ __pycache__/ *.o *.so .idea/ +/docs/*.1 +/docs/*.5 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..64aadda --- /dev/null +++ b/docs/README.md @@ -0,0 +1,23 @@ +# Documentation +## OpenAPI +We are using [OpenAPI 3.0](https://swagger.io/docs/specification/about/) to +document the REST API for ceod, and [Redoc](https://github.com/Redocly/redoc) +to generate HTML documentation from the OpenAPI file. + +First, make sure you have Node.js and npm installed. Then, install the Redoc CLI: +```sh +npm install -g redoc-cli +``` +After you make changes to the openapi.yaml file, make sure to regenerate the HTML: +```sh +redoc-cli bundle openapi.yaml +``` +You can now view the [redoc-static.html](./redoc-static.html) file from your browser. + +## Man pages +We are using [scdoc](https://git.sr.ht/~sircmpwn/scdoc) to generate our man pages. +You can view the pages from your terminal like so: +```sh +scdoc < ceo.1.scd > ceo.1 +man ./ceo.1 +``` diff --git a/docs/ceo.1.scd b/docs/ceo.1.scd new file mode 100644 index 0000000..08f3b26 --- /dev/null +++ b/docs/ceo.1.scd @@ -0,0 +1,29 @@ +ceo(1) + +# NAME + +ceo - CSC Electronic Office + +# SYNOPSIS + +*Text User Interface* + *ceo* + +*Command Line Interface* + *ceo* [OPTIONS] COMMAND [ARGS]... + +# DESCRIPTION +CSC Electronic Office is used to manage membership registration and user accounts for the Computer Science Club. + +To use the TUI, type *ceo* with no arguments. +To use the CLI, run *ceo --help*. + +# SEE ALSO + +*ceo.ini*(5), *ceod.ini*(5) + +# AUTHORS + +Max Erenberg ++ +Andrew Wang ++ +Rio Liu diff --git a/docs/ceo.ini.5.scd b/docs/ceo.ini.5.scd new file mode 100644 index 0000000..1b823bc --- /dev/null +++ b/docs/ceo.ini.5.scd @@ -0,0 +1,57 @@ +ceo.ini(5) + +# NAME + +ceo.ini - configuration file for ceo + +# SYNOPSIS + +/etc/csc/ceo.ini + +# DESCRIPTION + +ceo.ini is an INI file with various sections which control the behaviour of *ceo*(1). + +# DEFAULTS SECTION + _base_domain_++ + The domain name of CSC. Should be set to 'csclub.uwaterloo.ca'. + + _uw_domain_++ + The domain of UW. Should be set to 'uwaterloo.ca'. + +# CEOD SECTION + _admin_host_++ + The host with the ceod/admin Kerberos key. + + _database_host_++ + The host with the root password for MySQL and PostgreSQL. + + _mailman_host_++ + The host running Mailman. + + _use_https_++ + Whether to use HTTPS when connecting to ceod. Should be set to 'true'. + + _port_++ + The port on which ceod is listening. + +# POSITIONS SECTION + _required_++ + A comma-separated list of executive positions which must be fulfilled. + + _available_++ + A comma-separated list of available executive positions. + +# MYSQL SECTION + _host_++ + The host where MySQL is running. + +# POSTGRESQL SECTION + _host_++ + The host where PostgreSQL is running. + +# SEE ALSO +*ceo*(1) + +# AUTHORS +Max Erenberg diff --git a/docs/ceod.ini.5.scd b/docs/ceod.ini.5.scd new file mode 100644 index 0000000..e713199 --- /dev/null +++ b/docs/ceod.ini.5.scd @@ -0,0 +1,159 @@ +ceod.ini(5) + +# NAME + +ceod.ini - configuration file for ceod + +# SYNOPSIS + +/etc/csc/ceod.ini + +# DESCRIPTION + +ceod.ini is an INI file with various sections which control the behaviour of ceod. + +# DEFAULTS SECTION + _base_domain_++ + The domain name of CSC. Should be set to 'csclub.uwaterloo.ca'. + +# CEOD SECTION + _admin_host_++ + The host with the ceod/admin Kerberos key. + + _fs_root_host_++ + The host without NFS root squashing. + + _database_host_++ + The host with the root password for MySQL and PostgreSQL. + + _mailman_host_++ + The host running Mailman. + + _use_https_++ + Whether to use HTTPS when connecting to ceod. Should be set to 'true'. + + _port_++ + The port on which ceod is listening. + +# LDAP SECTION + _admin_principal_++ + The Kerberos principal which ceod should use for *kadmin*(1). + + _server_url_++ + The primary CSC LDAP server URL. + + _sasl_realm_++ + The CSC SASL realm for LDAP. Should be 'CSCLUB.UWATERLOO.CA'. + + _users_base_++ + The LDAP OU where users are stored. + + _groups_base_++ + The LDAP OU where groups are stored. + + _sudo_base_++ + The LDAP OU where *sudo*(8) roles are stored. + +# UWLDAP SECTION + _server_url_++ + The UW LDAP server URL. + + _base_++ + The LDAP OU where users are stored in the UW LDAP. + +# MEMBERS SECTION + _min_id_++ + The minimum UID number for members. + + _max_id_++ + The maximum UID number for members. + + _home_++ + The directory in which new members' home directories should be created. + + _skel_++ + The skeleton directory for new members. + +# CLUBS SECTION + _min_id_++ + The minimum UID number for club accounts. + + _max_id_++ + The maximum UID number for club accounts. + + _home_++ + The directory in which new club accounts' home directories should be created. + + _skel_++ + The skeleton directory for new club accounts. + +# MAIL SECTION + _smtp_url_++ + The SMTP URL where ceod should send emails. + + _smtp_starttls_++ + Whether ceod should use STARTTLS with the SMTP server or not. + +# MAILMAN3 SECTION + _api_base_url_++ + The base URL of the Mailman 3 API. + + _api_username_++ + The username to use when authenticating to the Mailman 3 API via HTTP Basic Auth. + + _api_password_++ + The password to use when authenticating to the Mailman 3 API via HTTP Basic Auth. + + _new_member_list_++ + The mailing list to which new members should be subscribed. + +# AUXILIARY GROUPS SECTION + Each key in this section contains a comma-separated list of auxiliary groups to + which members should be added when joining the primary group. For example, + + syscom = office,staff + + means that when someone joins the syscom group, they will also be added to the + office and staff groups. + +# AUXILIARY MAILING LISTS SECTION + Each key in this section contains a comma-separated list of auxiliary mailing lists to + which members should be subscribed when joining the primary group. For example, + + syscom = syscom,syscom-alerts + + means that when someone joins the syscom group, they will also be subscribed to the + syscom and syscom-alerts mailing lists. + +# POSITIONS SECTION + _required_++ + A comma-separated list of executive positions which must be fulfilled. + + _available_++ + A comma-separated list of available executive positions. + +# MYSQL SECTION + _host_++ + The host where MySQL is running. + + _username_++ + The username to use when connecting to MySQL. + + _password_++ + The password to use when connecting to MySQL. + +# POSTGRESQL SECTION + _host_++ + The host where PostgreSQL is running. + + _username_++ + The username to use when connecting to PostgreSQL. + + _password_++ + The password to use when connecting to PostgreSQL. + +# SEE ALSO +*ceo.ini*(5) + +# AUTHORS +Max Erenberg diff --git a/docs/openapi.yaml b/docs/openapi.yaml new file mode 100644 index 0000000..4ba25bd --- /dev/null +++ b/docs/openapi.yaml @@ -0,0 +1,861 @@ +openapi: 3.0.0 +info: + title: ceod - OpenAPI 3.0 + description: | + This is an OpenAPI specification of ceod, the CSC Electronic Office daemon. + Visit the [git repository](https://git.csclub.uwaterloo.ca/public/pyceo) for + more details. + ## Streaming Responses + Many endpoints return a "streaming response", which consists of a series of JSON + objects, one per line (the mimetype is text/plain). For example: + ``` + {"status": "in progress", "operation": "replace_login_shell"} + {"status": "in progress", "operation": "replace_forwarding_addresses"} + {"status": "completed", "result": "OK"} + ``` + Whenever an operation is completed, a corresponding JSON object will be streamed + from the server to the client. This allows the client to track the server's progress + in real time. + contact: + email: syscom@csclub.uwaterloo.ca + version: 1.0.0 +servers: +- url: https://phosphoric-acid.csclub.uwaterloo.ca:9987/api +tags: +- name: members + description: Operations on members and club reps +- name: groups + description: Operations on groups and clubs +- name: mailman + description: Operations on mailing list subscriptions +- name: uwldap + description: Operations related to the UW LDAP directory +- name: database + description: Operations related to databases +security: +- GSSAPIAuth: [] +paths: + /members: + post: + tags: ['members'] + summary: Create a new user + description: >- + Creates a new member or club rep. If `terms` is specified, a member is created; + if `non_member_terms` is specified, a club rep is created. + requestBody: + content: + application/json: + schema: + type: object + properties: + uid: + $ref: "#/components/schemas/UID" + cn: + $ref: "#/components/schemas/UserCN" + program: + $ref: "#/components/schemas/Program" + terms: + $ref: "#/components/schemas/Terms" + non_member_terms: + $ref: "#/components/schemas/NonMemberTerms" + forwarding_addresses: + $ref: "#/components/schemas/ForwardingAddresses" + responses: + "200": + description: Success + content: + text/plain: + schema: + type: string + description: Streaming response + example: | + {"status": "in progress", "operation": "add_user_to_ldap"} + {"status": "in progress", "operation": "add_group_to_ldap"} + {"status": "in progress", "operation": "add_user_to_kerberos"} + {"status": "in progress", "operation": "create_home_dir"} + {"status": "in progress", "operation": "send_welcome_message"} + {"status": "in progress", "operation": "subscribe_to_mailing_list"} + {"status": "in progress", "operation": "announce_new_user"} + {"status": "completed", "result": {"cn": "Calum Dalek", "uid": "ctdalek", "uid_number": 20001, "gid_number": 20001, "login_shell": "/bin/bash", "home_directory": "/users/ctdalek", "is_club": false, "program": "MAT/Mathematics Computer Science", "terms": ["f2021"], "forwarding_addresses": ["ctdalek@uwaterloo.ca"], "password": "Wlw1wOTofERTEBlXWzR6/MZL"}} + /members/{username}: + get: + tags: ['members'] + summary: Get information about a user + description: >- + Returns information about a member or club rep. The `forwarding_addresses` field + will only be present if the client is an authenticated syscom member. + parameters: + - name: username + in: path + description: username of the user to return + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/User" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + patch: + tags: ['members'] + summary: Modify a user + description: Replace the login shell and/or forwarding addresses of a user + parameters: + - name: username + in: path + description: username of the user to modify + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + login_shell: + $ref: "#/components/schemas/LoginShell" + forwarding_addresses: + $ref: "#/components/schemas/ForwardingAddresses" + responses: + "200": + description: Success + content: + text/plain: + schema: + type: string + description: Streaming response + example: | + {"status": "in progress", "operation": "replace_login_shell"} + {"status": "in progress", "operation": "replace_forwarding_addresses"} + {"status": "completed", "result": "OK"} + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + /members/{username}/renew: + post: + tags: ['members'] + summary: Renew a user + description: Add member **or** non-member terms to a user + parameters: + - name: username + in: path + description: username of the user to renew + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + oneOf: + - type: object + properties: + terms: + type: array + description: Terms for which this user will be a member + items: + $ref: "#/components/schemas/Term" + - type: object + properties: + non_member_terms: + type: array + description: Terms for which this user will be a club rep + items: + $ref: "#/components/schemas/Term" + example: {"terms": ["f2021"]} + responses: + "200": + description: Success + content: + application/json: + schema: + oneOf: + - type: object + properties: + terms_added: + type: array + description: Member terms which were added to this user + items: + $ref: "#/components/schemas/Term" + - type: object + properties: + non_member_terms_added: + type: array + description: Non-member terms which were added to this user + items: + $ref: "#/components/schemas/Term" + example: {"terms_added": ["f2021"]} + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + /members/{username}/pwreset: + post: + tags: ['members'] + summary: Reset a user's password + description: >- + Sets a user's password to a randomly generated string, and returns it. The user will be + prompted to set a new password on their next login. + parameters: + - name: username + in: path + description: username of the user whose password will be reset + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + password: + type: string + description: The user's new password + example: "EPGbJwLl1pmiWz8Wvu/MSs+v" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + /groups: + post: + tags: ['groups'] + summary: Create a new group + description: >- + Creates a new Unix group for a club. A new Unix user account with the same name will also be created. + A sudo role will be created allowing members of the group to become this user. + requestBody: + content: + application/json: + schema: + type: object + properties: + cn: + $ref: "#/components/schemas/GroupCN" + description: + $ref: "#/components/schemas/GroupDescription" + responses: + "200": + description: Success + content: + text/plain: + schema: + type: string + description: Streaming response + example: | + {"status": "in progress", "operation": "add_user_to_ldap"} + {"status": "in progress", "operation": "add_group_to_ldap"} + {"status": "in progress", "operation": "add_sudo_role"} + {"status": "in progress", "operation": "create_home_dir"} + {"status": "completed", "result": {"cn": "uwclub1", "gid_number": 30001, "description": "Club One", "members": []}} + /groups/{group_name}: + get: + tags: ['groups'] + summary: Get information about a group + description: Returns information about a group + security: [] + parameters: + - name: group_name + in: path + description: name of the group to return + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + cn: + $ref: "#/components/schemas/GroupCN" + description: + $ref: "#/components/schemas/GroupDescription" + gid_number: + $ref: "#/components/schemas/GIDNumber" + members: + type: array + description: Members of the group + items: + $ref: "#/components/schemas/UID" + "404": + $ref: "#/components/responses/GroupNotFoundErrorResponse" + /groups/{group_name}/members/{username}: + post: + tags: ['groups'] + summary: Add a member to a group + description: >- + Adds a member to a group. The member will also be added to any auxiliary groups + specified in ceod.conf. The member may also be added to auxiliary mailing lists. + parameters: + - name: group_name + in: path + description: name of the group to which the member will be added + required: true + schema: + type: string + - name: username + in: path + description: username of the member who will be added to the group + required: true + schema: + type: string + - name: subscribe_to_lists + in: query + description: whether the member should be subscribed to auxiliary mailing lists + schema: + type: boolean + default: true + responses: + "200": + description: Success + content: + text/plain: + schema: + type: string + example: | + {"status": "in progress", "operation": "add_user_to_group"} + {"status": "in progress", "operation": "add_user_to_auxiliary_groups"} + {"status": "in progress", "operation": "subscribe_user_to_auxiliary_mailing_lists"} + {"status": "completed", "result": {"added_to_groups": ["group2","group3"], "subscribed_to_lists": ["list1","list2"]}} + "404": + $ref: "#/components/responses/GroupNotFoundErrorResponse" + delete: + tags: ['groups'] + summary: Remove a member from a group + description: >- + Removes a member from a group. The member will also be removed from any auxiliary groups + specified in ceod.conf. The member may also be removed from auxiliary mailing lists. + parameters: + - name: group_name + in: path + description: name of the group from which the member will be removed + required: true + schema: + type: string + - name: username + in: path + description: username of the member who will be removed from the group + required: true + schema: + type: string + - name: unsubscribe_from_lists + in: query + description: whether the member should be unsubscribed from auxiliary mailing lists + schema: + type: boolean + default: true + responses: + "200": + description: Success + content: + text/plain: + schema: + type: string + example: | + {"status": "in progress", "operation": "remove_user_from_group"} + {"status": "in progress", "operation": "remove_user_from_auxiliary_groups"} + {"status": "in progress", "operation": "unsubscribe_user_from_auxiliary_mailing_lists"} + {"status": "completed", "result": {"removed_from_groups": ["group2","group3"], "unsubscribed_from_lists": ["list1","list2"]}} + "404": + $ref: "#/components/responses/GroupNotFoundErrorResponse" + /positions: + get: + tags: ['positions'] + summary: Show current positions + description: >- + Shows the list of positions and members holding them. + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + additionalProperties: + type: string + example: + president: user0 + vice-president: user1 + sysadmin: user2 + treasurer: + post: + tags: ['positions'] + summary: Update positions + description: >- + Update members for each positions. Members not specified in the parameters will be removed + from the position and unsubscribed from the exec's mailing list. New position holders will + be subscribed to the mailing list. + requestBody: + description: New position holders + required: true + content: + application/json: + schema: + type: object + additionalProperties: + type: string + example: + president: user0 + vice-president: user1 + sysadmin: user2 + treasurer: + responses: + "200": + description: Success + content: + text/plain: + schema: + type: string + description: Streaming response + example: | + {"status": "in progress", "operation": "update_positions_ldap"} + {"status": "in progress", "operation": "update_exec_group_ldap"} + {"status": "in progress", "operation": "subscribe_to_mailing_list"} + {"status": "completed", "result": "OK"} + "400": + description: Failed + content: + application/json: + schema: + type: object + properties: + error: + type: string + /mailman/{mailing_list}/{username}: + post: + tags: ['mailman'] + servers: + - url: "https://mail.csclub.uwaterloo.ca:9987/api" + summary: subscribe a user to a mailing list + description: Subscribes a user to a mailing list. + parameters: + - name: mailing_list + in: path + description: >- + The name of the list to which the user will be subscribed. If there is no '@' symbol, + then '@csclub.uwaterloo.ca' will be appended to the list name. + required: true + schema: + type: string + - name: username + in: path + required: true + description: >- + The user who will be subscribed to the list. If there is no '@' symbol, then '@csclub.uwaterloo.ca' + will be appended to he username; otherwise, the given email address will be subscribed. + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: OK + "404": + $ref: "#/components/responses/NoSuchListErrorResponse" + "409": + $ref: "#/components/responses/UserAlreadySubscribedErrorResponse" + delete: + tags: ['mailman'] + servers: + - url: "https://mail.csclub.uwaterloo.ca:9987/api" + summary: unsubscribe a user from a mailing list + description: Unsubscribes a user from a mailing list. + parameters: + - name: mailing_list + in: path + description: >- + The name of the list from which the user will be unsubscribed. If there is no '@' symbol, + then '@csclub.uwaterloo.ca' will be appended to the list name. + required: true + schema: + type: string + - name: username + in: path + required: true + description: >- + The user who will be unsubscribed from the list. If there is no '@' symbol, then '@csclub.uwaterloo.ca' + will be appended to he username; otherwise, the given email address will be unsubscribed. + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: OK + "404": + $ref: "#/components/responses/UserAlreadySubscribedOrNoSuchListErrorResponse" + /uwldap/{username}: + get: + tags: ['uwldap'] + security: [] + summary: get UWLDAP information for a user + description: Returns information about a user from the UW LDAP directory. + parameters: + - name: username + in: path + description: username of the user to return + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/UWLDAPUser" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + /uwldap/updateprograms: + post: + tags: ['uwldap'] + summary: update CSC programs from UWLDAP + description: | + Sync the 'program' attribute in the CSC LDAP with the UW LDAP. + The JSON request body may be omitted. + parameters: + - name: dry_run + in: query + description: >- + Whether to perform a dry run or not. If true, a list of members who *would* have been + changed is returned. + schema: + type: boolean + default: false + requestBody: + content: + application/json: + schema: + type: object + properties: + members: + type: array + description: If non-empty, only these members will be synced with UWLDAP + default: [] + items: + $ref: "#/components/schemas/UID" + responses: + "200": + description: Success + content: + application/json: + schema: + type: array + description: >- + A list of members whose programs were (or who would have been) changed. + Each item of the list is a 3-tuple of the form (username, old_program, new_program). + items: + type: array + items: + type: string + example: [['ctdalek', 'old_program', 'new_program']] + /db/mysql/{username}: + post: + tags: ['database'] + servers: + - url: https://caffeine.csclub.uwaterloo.ca:9987/api + summary: Create a MySQL database + description: Create a MySQL database for the user + parameters: + - name: username + in: path + description: name of the user to create MySQL database for + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + password: + type: string + description: The password to the database + example: {"password": "7fUi5rQr/lcpeEj4M86ZBbwM"} + "400": + $ref: "#/components/responses/InvalidUsernameErrorResponse" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + "409": + $ref: "#/components/responses/DBAlreadyCreatedErrorResponse" + "500": + $ref: "#/components/responses/DBConnectionOrPermissionErrorResponse" + /db/mysql/{username}/pwreset: + post: + tags: ['database'] + servers: + - url: https://caffeine.csclub.uwaterloo.ca:9987/api + summary: Reset MySQL database password + description: Reset the password for a user's MySQL database + parameters: + - name: username + in: path + description: name of the user to reset the MySQL database password for + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + password: + type: string + description: The new password to the database + example: {"password": "kM90d3G/eofIUxr9O3CQHTlP"} + "400": + $ref: "#/components/responses/InvalidUsernameErrorResponse" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + "500": + $ref: "#/components/responses/DBConnectionOrPermissionErrorResponse" + /db/postgresql/{username}: + post: + tags: ['database'] + servers: + - url: https://caffeine.csclub.uwaterloo.ca:9987/api + summary: Create a PostgreSQL database + description: Create a PostgreSQL database for the user + parameters: + - name: username + in: path + description: name of the user to create PostgreSQL database for + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + password: + type: string + description: The password to the database + example: {"password": "iHxd62DC7Qt1HyYRj18P6ujS"} + "400": + $ref: "#/components/responses/InvalidUsernameErrorResponse" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + "409": + $ref: "#/components/responses/DBAlreadyCreatedErrorResponse" + "500": + $ref: "#/components/responses/DBConnectionOrPermissionErrorResponse" + /db/postgresql/{username}/pwreset: + post: + tags: ['database'] + servers: + - url: https://caffeine.csclub.uwaterloo.ca:9987/api + summary: Reset PostgreSQL database password + description: Reset the password for a user's PostgreSQL database + parameters: + - name: username + in: path + description: name of the user to reset the PostgreSQL database password for + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + password: + type: string + description: The new password to the database + example: {"password": "CdPHT49iYAWzzKuhKTt2dNeu"} + "400": + $ref: "#/components/responses/InvalidUsernameErrorResponse" + "404": + $ref: "#/components/responses/UserNotFoundErrorResponse" + "500": + $ref: "#/components/responses/DBConnectionOrPermissionErrorResponse" +components: + securitySchemes: + GSSAPIAuth: + type: http + scheme: negotiate + description: | + ceod uses SPNEGO-based authentication over HTTP, as specified in [RFC 4559](https://datatracker.ietf.org/doc/html/rfc4559). + It is basically a base64-encoded Kerberos ticket wrapped in a HTTP header. For endpoints which make modifications + to LDAP, the Delegate flag must also be set. + + For example, with cURL: + ```sh + kinit + curl --negotiate -u : --service-name ceod --delegation always -X POST -d '{"terms":["w2022"]}' https://phosphoric-acid.csclub.uwaterloo.ca/api/members/ctdalek/renew + ``` + schemas: + UserCN: + type: string + description: Full name + example: Calum Dalek + UID: + type: string + description: Username + example: ctdalek + Program: + type: string + description: Academic program + example: MAT/Mathematics Computer Science + Terms: + type: array + description: Terms for which this user was a member + items: + $ref: "#/components/schemas/Term" + NonMemberTerms: + type: array + description: Terms for which this user was a club rep + items: + $ref: "#/components/schemas/Term" + LoginShell: + type: string + description: Login shell + example: /bin/bash + UIDNumber: + type: integer + description: UID number + example: 20001 + GIDNumber: + type: integer + description: GID number + example: 20001 + User: + type: object + properties: + cn: + $ref: "#/components/schemas/UserCN" + uid: + $ref: "#/components/schemas/UID" + uid_number: + $ref: "#/components/schemas/UIDNumber" + gid_number: + $ref: "#/components/schemas/GIDNumber" + home_directory: + type: string + description: Home directory + example: /users/ctdalek + is_club: + type: boolean + description: Whether this user is a club account or not + example: false + login_shell: + $ref: "#/components/schemas/LoginShell" + program: + $ref: "#/components/schemas/Program" + positions: + type: array + description: Positions held by this member + items: + type: string + example: president + terms: + $ref: "#/components/schemas/Terms" + non_member_terms: + $ref: "#/components/schemas/NonMemberTerms" + forwarding_addresses: + $ref: "#/components/schemas/ForwardingAddresses" + UWLDAPUser: + type: object + properties: + uid: + $ref: "#/components/schemas/UID" + cn: + $ref: "#/components/schemas/UserCN" + given_name: + type: string + description: Given name + example: Calum + sn: + type: string + description: Surname + example: Dalek + mail_local_addresses: + type: array + description: UW email addresses for this user + items: + type: string + format: email + example: ctdalek@uwaterloo.ca + ForwardingAddresses: + type: array + description: Forwarding addresses in ~/.forward + items: + type: string + format: email + example: ctdalek@uwaterloo.ca + Term: + type: string + description: Academic term + example: f2021 + GroupCN: + type: string + description: the name of the group + example: uwclub1 + GroupDescription: + type: string + description: a description of the group + example: Club One + responses: + ErrorResponse: &ErrorResponse + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error message + UserNotFoundErrorResponse: + <<: *ErrorResponse + description: User not found + GroupNotFoundErrorResponse: + <<: *ErrorResponse + description: Group not found + UserAlreadySubscribedErrorResponse: + <<: *ErrorResponse + description: User is already subscribed + NoSuchListErrorResponse: + <<: *ErrorResponse + description: Mailing list does not exist + UserAlreadySubscribedOrNoSuchListErrorResponse: + <<: *ErrorResponse + description: User is already subscribed or mailing list does not exist + DBAlreadyCreatedErrorResponse: + <<: *ErrorResponse + description: User already has a database + InvalidUsernameErrorResponse: + <<: *ErrorResponse + description: Username contains invalid characters + DBConnectionOrPermissionErrorResponse: + <<: *ErrorResponse + description: Unable to connect to database or action failed due to permissions + diff --git a/docs/redoc-static.html b/docs/redoc-static.html new file mode 100644 index 0000000..00ee29e --- /dev/null +++ b/docs/redoc-static.html @@ -0,0 +1,608 @@ + + + + + + ceod - OpenAPI 3.0 + + + +