1
0
mirror of https://github.com/Mailu/Mailu.git synced 2024-12-12 10:45:38 +02:00

Fix #3113. RESTful API was not correctly documented.

This commit is contained in:
Dimitri Huisman 2024-01-22 10:44:30 +00:00
parent e0c5dc5fe5
commit 8f86ffc6fd
No known key found for this signature in database
6 changed files with 61 additions and 49 deletions

View File

@ -27,7 +27,7 @@ class Aliases(Resource):
@alias.doc(security='Bearer')
@common.api_token_authorization
def get(self):
""" List aliases """
""" List all aliases """
return models.Alias.query.all()
@alias.doc('create_alias')
@ -63,7 +63,7 @@ class Alias(Resource):
@alias.doc(security='Bearer')
@common.api_token_authorization
def get(self, alias):
""" Find alias """
""" Look up the specified alias """
alias_found = models.Alias.query.filter_by(email = alias).first()
if alias_found is None:
return { 'code': 404, 'message': f'Alias {alias} cannot be found'}, 404
@ -78,7 +78,7 @@ class Alias(Resource):
@alias.doc(security='Bearer')
@common.api_token_authorization
def patch(self, alias):
""" Update alias """
""" Update the specfied alias """
data = api.payload
alias_found = models.Alias.query.filter_by(email = alias).first()
if alias_found is None:
@ -99,7 +99,7 @@ class Alias(Resource):
@alias.doc(security='Bearer')
@common.api_token_authorization
def delete(self, alias):
""" Delete alias """
""" Delete the specified alias """
alias_found = models.Alias.query.filter_by(email = alias).first()
if alias_found is None:
return { 'code': 404, 'message': f'Alias {alias} cannot be found'}, 404
@ -110,12 +110,12 @@ class Alias(Resource):
@alias.route('/destination/<string:domain>')
class AliasWithDest(Resource):
@alias.doc('find_alias_filter_domain')
@alias.response(200, 'Success', alias_fields)
@alias.marshal_with(alias_fields, code=200, description='Success' ,as_list=True, skip_none=True, mask=None)
@alias.response(404, 'Alias or domain not found', response_fields)
@alias.doc(security='Bearer')
@common.api_token_authorization
def get(self, domain):
""" Find aliases of domain """
""" Look up the aliases of the specified domain """
domain_found = models.Domain.query.filter_by(name=domain).first()
if domain_found is None:
return { 'code': 404, 'message': f'Domain {domain} cannot be found'}, 404
@ -123,4 +123,4 @@ class AliasWithDest(Resource):
if aliases_found.count == 0:
return { 'code': 404, 'message': f'No alias can be found for domain {domain}'}, 404
else:
return marshal(aliases_found, alias_fields), 200
return marshal(aliases_found, alias_fields, as_list=True), 200

View File

@ -81,7 +81,7 @@ class Domains(Resource):
@dom.doc(security='Bearer')
@common.api_token_authorization
def get(self):
""" List domains """
""" List all domains """
return models.Domain.query.all()
@dom.doc('create_domain')
@ -131,12 +131,13 @@ class Domains(Resource):
class Domain(Resource):
@dom.doc('find_domain')
@dom.response(200, 'Success', domain_fields)
@dom.marshal_with(domain_fields, code=200, description='Success', as_list=False, skip_none=True, mask=None)
@dom.response(400, 'Input validation exception', response_fields)
@dom.response(404, 'Domain not found', response_fields)
@dom.doc(security='Bearer')
@common.api_token_authorization
def get(self, domain):
""" Find domain by name """
""" Look up the specified domain """
if not validators.domain(domain):
return { 'code': 400, 'message': f'Domain {domain} is not a valid domain'}, 400
domain_found = models.Domain.query.get(domain)
@ -153,7 +154,7 @@ class Domain(Resource):
@dom.doc(security='Bearer')
@common.api_token_authorization
def patch(self, domain):
""" Update an existing domain """
""" Update the specified domain """
if not validators.domain(domain):
return { 'code': 400, 'message': f'Domain {domain} is not a valid domain'}, 400
domain_found = models.Domain.query.get(domain)
@ -197,7 +198,7 @@ class Domain(Resource):
@dom.doc(security='Bearer')
@common.api_token_authorization
def delete(self, domain):
""" Delete domain """
""" Delete the specified domain """
if not validators.domain(domain):
return { 'code': 400, 'message': f'Domain {domain} is not a valid domain'}, 400
domain_found = models.Domain.query.get(domain)
@ -216,7 +217,7 @@ class Domain(Resource):
@dom.doc(security='Bearer')
@common.api_token_authorization
def post(self, domain):
""" Generate new DKIM/DMARC keys for domain """
""" Generate new DKIM/DMARC keys for the specified domain """
if not validators.domain(domain):
return { 'code': 400, 'message': f'Domain {domain} is not a valid domain'}, 400
domain_found = models.Domain.query.get(domain)
@ -229,13 +230,13 @@ class Domain(Resource):
@dom.route('/<domain>/manager')
class Manager(Resource):
@dom.doc('list_managers')
@dom.marshal_with(manager_fields, as_list=True, skip_none=True, mask=None)
@dom.marshal_with(manager_fields, code=200, description='Success', as_list=True, skip_none=True, mask=None)
@dom.response(400, 'Input validation exception', response_fields)
@dom.response(404, 'domain not found', response_fields)
@dom.doc(security='Bearer')
@common.api_token_authorization
def get(self, domain):
""" List managers of domain """
""" List all managers of the specified domain """
if not validators.domain(domain):
return { 'code': 400, 'message': f'Domain {domain} is not a valid domain'}, 400
if not domain:
@ -252,7 +253,7 @@ class Manager(Resource):
@dom.doc(security='Bearer')
@common.api_token_authorization
def post(self, domain):
""" Create a new domain manager """
""" Create a new domain manager for the specified domain """
data = api.payload
if not validators.email(data['user_email']):
return {'code': 400, 'message': f'Invalid email address {data["user_email"]}'}, 400
@ -273,12 +274,13 @@ class Manager(Resource):
@dom.route('/<domain>/manager/<email>')
class Domain(Resource):
@dom.doc('find_manager')
@dom.response(200, 'Success', manager_fields)
@dom.marshal_with(manager_fields, code=200, description='Success', as_list=False, skip_none=True, mask=None)
@dom.response(400, 'Input validation exception', response_fields)
@dom.response(404, 'Manager not found', response_fields)
@dom.doc(security='Bearer')
@common.api_token_authorization
def get(self, domain, email):
""" Find manager by email address """
""" Look up the specified manager of the specified domain """
if not validators.email(email):
return {'code': 400, 'message': f'Invalid email address {email}'}, 400
if not validators.domain(domain):
@ -304,6 +306,7 @@ class Domain(Resource):
@dom.doc(security='Bearer')
@common.api_token_authorization
def delete(self, domain, email):
""" Delete the specified manager of the specified domain """
if not validators.email(email):
return {'code': 400, 'message': f'Invalid email address {email}'}, 400
if not validators.domain(domain):
@ -324,13 +327,13 @@ class Domain(Resource):
@dom.route('/<domain>/users')
class User(Resource):
@dom.doc('list_user_domain')
@dom.marshal_with(user.user_fields_get, as_list=True, skip_none=True, mask=None)
@dom.marshal_with(user.user_fields_get, code=200, description='Success', as_list=True, skip_none=True, mask=None)
@dom.response(400, 'Input validation exception', response_fields)
@dom.response(404, 'Domain not found', response_fields)
@dom.doc(security='Bearer')
@common.api_token_authorization
def get(self, domain):
""" List users from domain """
""" List all the users from the specified domain """
if not validators.domain(domain):
return { 'code': 400, 'message': f'Domain {domain} is not a valid domain'}, 400
domain_found = models.Domain.query.get(domain)
@ -346,7 +349,7 @@ class Alternatives(Resource):
@alt.doc(security='Bearer')
@common.api_token_authorization
def get(self):
""" List alternatives """
""" List all alternatives """
return models.Alternative.query.all()
@ -359,7 +362,7 @@ class Alternatives(Resource):
@alt.doc(security='Bearer')
@common.api_token_authorization
def post(self):
""" Create new alternative (for domain) """
""" Create a new alternative (for domain) """
data = api.payload
if not validators.domain(data['name']):
return { 'code': 400, 'message': f'Alternative domain {data["name"]} is not a valid domain'}, 400
@ -380,9 +383,12 @@ class Alternatives(Resource):
class Alternative(Resource):
@alt.doc('find_alternative')
@alt.doc(security='Bearer')
@alt.marshal_with(alternative_fields, code=200, description='Success' ,as_list=True, skip_none=True, mask=None)
@alt.response(400, 'Input validation exception', response_fields)
@alt.response(404, 'Alternative not found or missing', response_fields)
@common.api_token_authorization
def get(self, alt):
""" Find alternative (of domain) """
""" Look up the specified alternative (of domain) """
if not validators.domain(alt):
return { 'code': 400, 'message': f'Alternative domain {alt} is not a valid domain'}, 400
alternative = models.Alternative.query.filter_by(name=alt).first()
@ -398,7 +404,7 @@ class Alternative(Resource):
@alt.doc(security='Bearer')
@common.api_token_authorization
def delete(self, alt):
""" Delete alternative (for domain) """
""" Delete the specified alternative (for domain) """
if not validators.domain(alt):
return { 'code': 400, 'message': f'Alternative domain {alt} is not a valid domain'}, 400
alternative = models.Alternative.query.filter_by(name=alt).scalar()

View File

@ -27,22 +27,22 @@ class Relays(Resource):
@relay.doc(security='Bearer')
@common.api_token_authorization
def get(self):
"List relays"
"List all relays"
return models.Relay.query.all()
@relay.doc('create_relay')
@relay.expect(relay_fields)
@relay.response(200, 'Success', response_fields)
@relay.response(400, 'Input validation exception')
@relay.response(400, 'Input validation exception', response_fields)
@relay.response(409, 'Duplicate relay', response_fields)
@relay.doc(security='Bearer')
@common.api_token_authorization
def post(self):
""" Create relay """
""" Create a new relay """
data = api.payload
if not validators.domain(name):
return { 'code': 400, 'message': f'Relayed domain {name} is not a valid domain'}, 400
if not validators.domain(data['name']):
return { 'code': 400, 'message': f'Relayed domain {data["name"]} is not a valid domain'}, 400
if common.fqdn_in_use(data['name']):
return { 'code': 409, 'message': f'Duplicate domain {data["name"]}'}, 409
@ -58,12 +58,13 @@ class Relays(Resource):
@relay.route('/<string:name>')
class Relay(Resource):
@relay.doc('find_relay')
@relay.marshal_with(relay_fields, code=200, description='Success', as_list=False, skip_none=True, mask=None)
@relay.response(400, 'Input validation exception', response_fields)
@relay.response(404, 'Relay not found', response_fields)
@relay.doc(security='Bearer')
@common.api_token_authorization
def get(self, name):
""" Find relay """
""" Look up the specified relay """
if not validators.domain(name):
return { 'code': 400, 'message': f'Relayed domain {name} is not a valid domain'}, 400
@ -81,7 +82,7 @@ class Relay(Resource):
@relay.doc(security='Bearer')
@common.api_token_authorization
def patch(self, name):
""" Update relay """
""" Update the specified relay """
data = api.payload
if not validators.domain(name):
@ -107,7 +108,7 @@ class Relay(Resource):
@relay.doc(security='Bearer')
@common.api_token_authorization
def delete(self, name):
""" Delete relay """
""" Delete the specified relay """
if not validators.domain(name):
return { 'code': 400, 'message': f'Relayed domain {name} is not a valid domain'}, 400
relay_found = models.Relay.query.filter_by(name=name).first()

View File

@ -47,13 +47,13 @@ class Tokens(Resource):
@token.doc(security='Bearer')
@common.api_token_authorization
def get(self):
"""List tokens"""
"""List all tokens"""
return models.Token.query.all()
@token.doc('create_token')
@token.expect(token_user_fields_post)
@token.response(200, 'Success', token_user_post_response)
@token.response(400, 'Input validation exception')
@token.marshal_with(token_user_post_response, code=200, description='Success', as_list=False, skip_none=True, mask=None)
@token.response(400, 'Input validation exception', response_fields)
@token.response(409, 'Duplicate relay', response_fields)
@token.doc(security='Bearer')
@common.api_token_authorization
@ -92,11 +92,13 @@ class Tokens(Resource):
@token.route('user/<string:email>')
class Token(Resource):
@token.doc('find_tokens_of_user')
@token.marshal_with(token_user_fields, as_list=True, skip_none=True, mask=None)
@token.marshal_with(token_user_fields, code=200, description='Success', as_list=True, skip_none=True, mask=None)
@token.response(400, 'Input validation exception', response_fields)
@token.response(404, 'Token not found', response_fields)
@token.doc(security='Bearer')
@common.api_token_authorization
def get(self, email):
"Find tokens of user"
""" Look up all the tokens of the specified user """
if not validators.email(email):
return { 'code': 400, 'message': f'Provided email address {email} is not a valid email address'}, 400
user_found = models.User.query.get(email)
@ -108,12 +110,12 @@ class Token(Resource):
@token.doc('create_token')
@token.expect(token_user_fields_post2)
@token.response(200, 'Success', token_user_post_response)
@token.response(400, 'Input validation exception')
@token.response(400, 'Input validation exception', response_fields)
@token.response(409, 'Duplicate relay', response_fields)
@token.doc(security='Bearer')
@common.api_token_authorization
def post(self, email):
""" Create a new token for user"""
""" Create a new token for the specified user"""
data = api.payload
if not validators.email(email):
return { 'code': 400, 'message': f'Provided email address {email} is not a valid email address'}, 400
@ -144,11 +146,12 @@ class Token(Resource):
@token.route('/<string:token_id>')
class Token(Resource):
@token.doc('find_token')
@token.marshal_with(token_user_fields, as_list=True, skip_none=True, mask=None)
@token.marshal_with(token_user_fields, code=200, description='Success', as_list=False, skip_none=True, mask=None)
@token.response(404, 'Token not found', response_fields)
@token.doc(security='Bearer')
@common.api_token_authorization
def get(self, token_id):
"Find token"
"Find the specified token"
token = models.Token.query.get(token_id)
if not token:
return { 'code' : 404, 'message' : f'Record cannot be found for id {token_id} or invalid id provided'}, 404
@ -161,7 +164,7 @@ class Token(Resource):
@token.doc(security='Bearer')
@common.api_token_authorization
def delete(self, token_id):
""" Delete token """
""" Delete the specified token """
token = models.Token.query.get(token_id)
if not token:
return { 'code' : 404, 'message' : f'Record cannot be found for id {token_id} or invalid id provided'}, 404

View File

@ -87,23 +87,23 @@ user_fields_put = api.model('UserUpdate', {
@user.route('')
class Users(Resource):
@user.doc('list_users')
@user.doc('list_user')
@user.marshal_with(user_fields_get, as_list=True, skip_none=True, mask=None)
@user.doc(security='Bearer')
@common.api_token_authorization
def get(self):
"List users"
"List all users"
return models.User.query.all()
@user.doc('create_user')
@user.expect(user_fields_post)
@user.response(200, 'Success', response_fields)
@user.response(400, 'Input validation exception')
@user.response(400, 'Input validation exception', response_fields)
@user.response(409, 'Duplicate user', response_fields)
@user.doc(security='Bearer')
@common.api_token_authorization
def post(self):
""" Create user """
""" Create a new user """
data = api.payload
if not validators.email(data['email']):
return { 'code': 400, 'message': f'Provided email address {data["email"]} is not a valid email address'}, 400
@ -168,12 +168,13 @@ class Users(Resource):
@user.route('/<string:email>')
class User(Resource):
@user.doc('find_user')
@user.marshal_with(user_fields_get, code=200, description='Success', as_list=False, skip_none=True, mask=None)
@user.response(400, 'Input validation exception', response_fields)
@user.response(404, 'User not found', response_fields)
@user.doc(security='Bearer')
@common.api_token_authorization
def get(self, email):
""" Find user """
""" Look up the specified user """
if not validators.email(email):
return { 'code': 400, 'message': f'Provided email address {email} is not a valid email address'}, 400
@ -191,7 +192,7 @@ class User(Resource):
@user.doc(security='Bearer')
@common.api_token_authorization
def patch(self, email):
""" Update user """
""" Update the specified user """
data = api.payload
if not validators.email(email):
return { 'code': 400, 'message': f'Provided email address {data["email"]} is not a valid email address'}, 400
@ -258,7 +259,7 @@ class User(Resource):
@user.doc(security='Bearer')
@common.api_token_authorization
def delete(self, email):
""" Delete user """
""" Delete the specified user """
if not validators.email(email):
return { 'code': 400, 'message': f'Provided email address {email} is not a valid email address'}, 400

View File

@ -0,0 +1 @@
Some RESTful API interfaces were incorrectly documented.