mirror of
https://github.com/alerta/alerta.git
synced 2025-01-24 01:10:24 +00:00
431 lines
17 KiB
Python
431 lines
17 KiB
Python
import json
|
|
import unittest
|
|
|
|
from flask import g
|
|
|
|
from alerta.app import create_app, db, plugins
|
|
from alerta.exceptions import ApiError
|
|
from alerta.models.enums import Scope
|
|
from alerta.models.key import ApiKey
|
|
from alerta.utils.api import assign_customer
|
|
|
|
|
|
class CustomersTestCase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
test_config = {
|
|
'TESTING': True,
|
|
'AUTH_REQUIRED': True,
|
|
'CUSTOMER_VIEWS': True,
|
|
'ADMIN_USERS': ['admin@alerta.io'],
|
|
'ALLOWED_EMAIL_DOMAINS': ['alerta.io', 'foo.com', 'bar.com']
|
|
}
|
|
self.app = create_app(test_config)
|
|
self.client = self.app.test_client()
|
|
|
|
self.foo_alert = {
|
|
'event': 'foo1',
|
|
'resource': 'foo1',
|
|
'environment': 'Production',
|
|
'service': ['Web']
|
|
}
|
|
|
|
self.bar_alert = {
|
|
'event': 'bar1',
|
|
'resource': 'bar1',
|
|
'environment': 'Production',
|
|
'service': ['Web']
|
|
}
|
|
|
|
with self.app.test_request_context('/'):
|
|
self.app.preprocess_request()
|
|
self.api_key = ApiKey(
|
|
user='admin@alerta.io',
|
|
scopes=[Scope.admin, Scope.read, Scope.write],
|
|
text='admin-key'
|
|
)
|
|
self.api_key.create()
|
|
|
|
self.admin_headers = {
|
|
'Authorization': f'Key {self.api_key.key}',
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
def tearDown(self):
|
|
plugins.plugins.clear()
|
|
db.destroy()
|
|
|
|
def test_customers(self):
|
|
|
|
# add customer mappings
|
|
payload = {
|
|
'customer': 'Bar Corp',
|
|
'match': 'bar.com'
|
|
}
|
|
response = self.client.post('/customer', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
payload = {
|
|
'customer': 'Foo Bar Corp',
|
|
'match': 'foo@bar.com'
|
|
}
|
|
response = self.client.post('/customer', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
response = self.client.get('/customers', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# create users
|
|
payload = {
|
|
'name': 'Bar User',
|
|
'email': 'user@bar.com',
|
|
'password': 'b8rb8r',
|
|
'text': ''
|
|
}
|
|
|
|
response = self.client.post('/auth/signup', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200, response.data)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data, 'Failed to create user')
|
|
|
|
self.bar_bearer_headers = {
|
|
'Authorization': f"Bearer {data['token']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
payload = {
|
|
'name': 'Foo Bar User',
|
|
'email': 'foo@bar.com',
|
|
'password': 'f00b8r',
|
|
'text': ''
|
|
}
|
|
|
|
response = self.client.post('/auth/signup', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data, 'Failed to create user')
|
|
|
|
self.foobar_bearer_headers = {
|
|
'Authorization': f"Bearer {data['token']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
# create API key for user@bar.com
|
|
payload = {
|
|
'user': 'user@bar.com',
|
|
'scopes': ['read', 'write'],
|
|
'text': ''
|
|
}
|
|
|
|
response = self.client.post('/key', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.bar_bearer_headers)
|
|
self.assertEqual(response.status_code, 201, response.data)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data['key'], 'Failed to create read-write key')
|
|
|
|
self.bar_api_key_headers = {
|
|
'Authorization': f"Key {data['key']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
# create API keys for foo@bar.com
|
|
payload = {
|
|
'user': 'foo@bar.com',
|
|
'scopes': ['read', 'write'],
|
|
'text': '',
|
|
'customer': 'Foo Bar Corp'
|
|
}
|
|
|
|
response = self.client.post('/key', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.foobar_bearer_headers)
|
|
self.assertEqual(response.status_code, 201, response.data)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data['key'], 'Failed to create read-write key')
|
|
|
|
self.foobar_api_key_headers = {
|
|
'Authorization': f"Key {data['key']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
payload = {
|
|
'user': 'foo@bar.com',
|
|
'scopes': ['read', 'write'],
|
|
'text': '',
|
|
'customer': 'Bar Corp'
|
|
}
|
|
|
|
response = self.client.post('/key', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.foobar_bearer_headers)
|
|
self.assertEqual(response.status_code, 201, response.data)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data['key'], 'Failed to create read-write key')
|
|
|
|
self.foobar_bar_only_api_key_headers = {
|
|
'Authorization': f"Key {data['key']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
# get list of customers for users
|
|
response = self.client.get('/customers', headers=self.bar_api_key_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual([c['customer'] for c in data['customers']], ['Bar Corp'])
|
|
|
|
response = self.client.get('/customers', headers=self.foobar_api_key_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual([c['customer'] for c in data['customers']], ['Foo Bar Corp'])
|
|
|
|
# create alerts using API keys
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.bar_api_key_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['alert']['customer'], 'Bar Corp')
|
|
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.foobar_api_key_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['alert']['customer'], 'Foo Bar Corp')
|
|
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert),
|
|
headers=self.foobar_bar_only_api_key_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['alert']['customer'], 'Bar Corp')
|
|
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert),
|
|
headers=self.foobar_bar_only_api_key_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['alert']['customer'], 'Bar Corp')
|
|
|
|
# create alerts using Bearer tokens
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.bar_bearer_headers)
|
|
self.assertEqual(response.status_code, 201, response.data)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['alert']['customer'], 'Bar Corp')
|
|
|
|
self.foo_alert['customer'] = 'Foo Bar Corp'
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.foobar_bearer_headers)
|
|
self.assertEqual(response.status_code, 201, response.data)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['alert']['customer'], 'Foo Bar Corp')
|
|
|
|
def test_blackouts(self):
|
|
|
|
# add customer mappings
|
|
payload = {
|
|
'customer': 'Foo Corp',
|
|
'match': 'foo.com'
|
|
}
|
|
response = self.client.post('/customer', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
payload = {
|
|
'customer': 'Bar Corp',
|
|
'match': 'bar.com'
|
|
}
|
|
response = self.client.post('/customer', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
# create users
|
|
payload = {
|
|
'name': 'Foo User',
|
|
'email': 'user@foo.com',
|
|
'password': 'f00f00',
|
|
'text': ''
|
|
}
|
|
|
|
response = self.client.post('/auth/signup', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data, 'Failed to create user')
|
|
|
|
foo_user_headers = {
|
|
'Authorization': f"Bearer {data['token']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
payload = {
|
|
'name': 'Bar User',
|
|
'email': 'user@bar.com',
|
|
'password': 'b8rb8r',
|
|
'text': ''
|
|
}
|
|
|
|
response = self.client.post('/auth/signup', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertIsNotNone(data, 'Failed to create user')
|
|
|
|
bar_user_headers = {
|
|
'Authorization': f"Bearer {data['token']}",
|
|
'Content-type': 'application/json'
|
|
}
|
|
|
|
# create customer blackout by foo user
|
|
response = self.client.post(
|
|
'/blackout', data=json.dumps({'environment': 'Production'}), headers=foo_user_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
|
|
blackout_id = data['id']
|
|
|
|
# new alert by foo user should be suppressed
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=foo_user_headers)
|
|
self.assertEqual(response.status_code, 202)
|
|
|
|
# new alert by bar user should not be suppressed
|
|
response = self.client.post('/alert', data=json.dumps(self.bar_alert), headers=bar_user_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
# delete blackout by id
|
|
response = self.client.delete('/blackout/' + blackout_id, headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# create global blackout by admin user
|
|
response = self.client.post(
|
|
'/blackout', data=json.dumps({'environment': 'Production'}), headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
|
|
blackout_id = data['id']
|
|
|
|
# new alert by foo user should be suppressed
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=foo_user_headers)
|
|
self.assertEqual(response.status_code, 202)
|
|
|
|
# new alert by bar user should be suppressed
|
|
response = self.client.post('/alert', data=json.dumps(self.bar_alert), headers=bar_user_headers)
|
|
self.assertEqual(response.status_code, 202)
|
|
|
|
# delete blackout by id
|
|
response = self.client.delete('/blackout/' + blackout_id, headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_assign_customer(self):
|
|
|
|
with self.app.test_request_context('/'):
|
|
self.app.preprocess_request()
|
|
|
|
# nothing wanted, assign one
|
|
g.customers = ['Customer1']
|
|
g.scopes = []
|
|
self.assertEqual(assign_customer(wanted=None), 'Customer1')
|
|
|
|
# nothing wanted, but too many, throw error
|
|
g.customers = ['Customer1', 'Customer2']
|
|
g.scopes = []
|
|
with self.assertRaises(ApiError) as e:
|
|
assign_customer(wanted=None)
|
|
exc = e.exception
|
|
self.assertEqual(str(exc), 'must define customer as more than one possibility')
|
|
|
|
# customer wanted, matches so allow
|
|
g.customers = ['Customer1']
|
|
g.scopes = []
|
|
self.assertEqual(assign_customer(wanted='Customer1'), 'Customer1')
|
|
|
|
# customer wanted, in list so allow
|
|
g.customers = ['Customer1', 'Customer2']
|
|
g.scopes = []
|
|
self.assertEqual(assign_customer(wanted='Customer2'), 'Customer2')
|
|
|
|
# customer wanted not in list, throw exception
|
|
g.customers = ['Customer1', 'Customer2']
|
|
g.scopes = []
|
|
with self.assertRaises(ApiError) as e:
|
|
assign_customer(wanted='Customer3')
|
|
exc = e.exception
|
|
self.assertEqual(str(exc), "not allowed to set customer to 'Customer3'")
|
|
|
|
# no customers, admin scope so allow
|
|
g.customers = []
|
|
g.scopes = ['admin']
|
|
self.assertEqual(assign_customer(wanted=None), None)
|
|
self.assertEqual(assign_customer(wanted='Customer1'), 'Customer1')
|
|
|
|
g.customers = ['Customer1', 'Customer2']
|
|
g.scopes = ['admin']
|
|
with self.assertRaises(ApiError) as e:
|
|
assign_customer(wanted=None)
|
|
exc = e.exception
|
|
self.assertEqual(str(exc), 'must define customer as more than one possibility')
|
|
self.assertEqual(assign_customer(wanted='Customer3'), 'Customer3')
|
|
|
|
# wrong scope
|
|
g.customers = ['Customer1']
|
|
g.scopes = ['read:keys', 'write:keys']
|
|
with self.assertRaises(ApiError) as e:
|
|
assign_customer(wanted='Customer2', permission=Scope.admin_keys)
|
|
exc = e.exception
|
|
self.assertEqual(str(exc), "not allowed to set customer to 'Customer2'")
|
|
|
|
# right scope
|
|
g.customers = ['Customer1']
|
|
g.scopes = ['admin:keys', 'read:keys', 'write:keys']
|
|
self.assertEqual(assign_customer(wanted='Customer2', permission=Scope.admin_keys), 'Customer2')
|
|
|
|
def test_invalid_customer(self):
|
|
|
|
self.foo_alert['customer'] = ''
|
|
|
|
response = self.client.post('/alert', data=json.dumps(self.foo_alert), headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 400)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['message'], 'customer must not be an empty string')
|
|
|
|
def test_edit_customer(self):
|
|
|
|
# add customer mappings
|
|
payload = {
|
|
'customer': 'Foo Corp',
|
|
'match': 'foo.com'
|
|
}
|
|
response = self.client.post('/customer', data=json.dumps(payload),
|
|
content_type='application/json', headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 201)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
|
|
customer_id = data['id']
|
|
|
|
# change customer name
|
|
update = {
|
|
'customer': 'Bar Corp'
|
|
}
|
|
response = self.client.put('/customer/' + customer_id, data=json.dumps(update), headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['status'], 'ok')
|
|
|
|
# check updates worked and didn't change anything else
|
|
response = self.client.get('/customer/' + customer_id, headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['customer']['customer'], 'Bar Corp')
|
|
self.assertEqual(data['customer']['match'], 'foo.com')
|
|
|
|
# change customer lookup
|
|
update = {
|
|
'match': 'bar.com'
|
|
}
|
|
response = self.client.put('/customer/' + customer_id, data=json.dumps(update), headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['status'], 'ok')
|
|
|
|
# check updates worked and didn't change anything else
|
|
response = self.client.get('/customer/' + customer_id, headers=self.admin_headers)
|
|
self.assertEqual(response.status_code, 200)
|
|
data = json.loads(response.data.decode('utf-8'))
|
|
self.assertEqual(data['customer']['customer'], 'Bar Corp')
|
|
self.assertEqual(data['customer']['match'], 'bar.com')
|