start OpenAPI spec

This commit is contained in:
Max Erenberg 2021-09-27 01:02:16 -04:00
parent 7edc01e42b
commit 6e1c866e2b
2 changed files with 1223 additions and 0 deletions

654
docs/openapi.yaml Normal file
View File

@ -0,0 +1,654 @@
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
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"
/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']]
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

569
docs/redoc-static.html Normal file

File diff suppressed because one or more lines are too long