diff --git a/api/app.py b/api/app.py index a63f3bf..1774f0d 100644 --- a/api/app.py +++ b/api/app.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- """The app module, containing the app factory function.""" +import logging import os import sys -import logging -from logging.handlers import RotatingFileHandler from inspect import getmembers +from logging.handlers import RotatingFileHandler from flask import Flask from flask import make_response, jsonify @@ -12,8 +12,6 @@ from flask.blueprints import Blueprint from flask.cli import click import api.views -from api.models.account import User -from api.flask_cas import CAS from api.extensions import ( bcrypt, cors, @@ -24,6 +22,8 @@ from api.extensions import ( celery, rd, ) +from api.flask_cas import CAS +from api.models.account import User HERE = os.path.abspath(os.path.dirname(__file__)) PROJECT_ROOT = os.path.join(HERE, os.pardir) diff --git a/api/commands/common.py b/api/commands/common.py index 1abe98b..526543f 100644 --- a/api/commands/common.py +++ b/api/commands/common.py @@ -110,7 +110,7 @@ def urls(url, order): column_length = 1 else: rules = sorted( - current_app.url_map.iter_rules(), key=lambda rule: getattr(rule, order) + current_app.url_map.iter_rules(), key=lambda x: getattr(x, order) ) for rule in rules: rows.append((rule.rule, rule.endpoint, None)) diff --git a/api/extensions.py b/api/extensions.py index 02706db..bec8ea6 100644 --- a/api/extensions.py +++ b/api/extensions.py @@ -1,13 +1,13 @@ # -*- coding:utf-8 -*- +from celery import Celery from flask_bcrypt import Bcrypt from flask_caching import Cache +from flask_cors import CORS from flask_login import LoginManager from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy -from flask_cors import CORS -from celery import Celery from api.lib.utils import RedisHandler diff --git a/api/flask_cas/__init__.py b/api/flask_cas/__init__.py index dc31cf5..70dc5fe 100644 --- a/api/flask_cas/__init__.py +++ b/api/flask_cas/__init__.py @@ -75,4 +75,4 @@ class CAS(object): @property def token(self): return flask.session.get( - self.app.config['CAS_TOKEN_SESSION_KEY'], None) \ No newline at end of file + self.app.config['CAS_TOKEN_SESSION_KEY'], None) diff --git a/api/flask_cas/cas_urls.py b/api/flask_cas/cas_urls.py index 34e15d3..6d460eb 100644 --- a/api/flask_cas/cas_urls.py +++ b/api/flask_cas/cas_urls.py @@ -68,7 +68,7 @@ def create_cas_login_url(cas_url, cas_route, service, ('service', service), ('renew', renew), ('gateway', gateway), - ) + ) def create_cas_logout_url(cas_url, cas_route, url=None): @@ -91,7 +91,7 @@ def create_cas_logout_url(cas_url, cas_route, url=None): cas_url, cas_route, ('service', url), - ) + ) def create_cas_validate_url(cas_url, cas_route, service, ticket, @@ -119,4 +119,4 @@ def create_cas_validate_url(cas_url, cas_route, service, ticket, ('service', service), ('ticket', ticket), ('renew', renew), - ) \ No newline at end of file + ) diff --git a/api/flask_cas/routing.py b/api/flask_cas/routing.py index e726f32..41c0086 100644 --- a/api/flask_cas/routing.py +++ b/api/flask_cas/routing.py @@ -3,18 +3,16 @@ import json import bs4 +from flask import Blueprint +from flask import current_app, session, request, url_for, redirect +from flask_login import login_user, logout_user from six.moves.urllib_request import urlopen -from flask import Blueprint -from flask_login import login_user, logout_user -from flask import current_app, session, request, url_for, redirect - +from api.models.account import UserCache from .cas_urls import create_cas_login_url from .cas_urls import create_cas_logout_url from .cas_urls import create_cas_validate_url -from api.models.account import UserCache - blueprint = Blueprint('cas', __name__) diff --git a/api/lib/cmdb/attribute.py b/api/lib/cmdb/attribute.py index efe235c..82bce55 100644 --- a/api/lib/cmdb/attribute.py +++ b/api/lib/cmdb/attribute.py @@ -1,15 +1,15 @@ # -*- coding:utf-8 -*- -from flask import current_app from flask import abort +from flask import current_app from api.extensions import db -from api.models.cmdb import Attribute -from api.models.cmdb import CITypeAttribute -from api.models.cmdb import PreferenceShowAttributes from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.const import type_map from api.lib.decorator import kwargs_required +from api.models.cmdb import Attribute +from api.models.cmdb import CITypeAttribute +from api.models.cmdb import PreferenceShowAttributes class AttributeManager(object): @@ -97,7 +97,8 @@ class AttributeManager(object): alias = kwargs.pop("alias", "") alias = name if not alias else alias Attribute.get_by(name=name, first=True) and abort(400, "attribute name <{0}> is already existed".format(name)) - Attribute.get_by(alias=alias, first=True) and abort(400, "attribute alias <{0}> is already existed".format(name)) + Attribute.get_by(alias=alias, first=True) and abort(400, + "attribute alias <{0}> is already existed".format(name)) attr = Attribute.create(flush=True, name=name, diff --git a/api/lib/cmdb/cache.py b/api/lib/cmdb/cache.py index 629463e..45a6ee2 100644 --- a/api/lib/cmdb/cache.py +++ b/api/lib/cmdb/cache.py @@ -10,73 +10,84 @@ from api.models.cmdb import RelationType class AttributeCache(object): + PREFIX_ID = 'Field::ID::{0}' + PREFIX_NAME = 'Field::Name::{0}' + PREFIX_ALIAS = 'Field::Alias::{0}' + @classmethod def get(cls, key): if key is None: return - attr = cache.get('Field::Name::{0}'.format(key)) \ - or cache.get('Field::ID::{0}'.format(key)) \ - or cache.get('Field::Alias::{0}'.format(key)) + attr = cache.get(cls.PREFIX_NAME.format(key)) + attr = attr or cache.get(cls.PREFIX_ID.format(key)) + attr = attr or cache.get(cls.PREFIX_ALIAS.format(key)) if attr is None: - attr = Attribute.get_by(name=key, first=True, to_dict=False) \ - or Attribute.get_by_id(key) \ - or Attribute.get_by(alias=key, first=True, to_dict=False) + attr = Attribute.get_by(name=key, first=True, to_dict=False) + attr = attr or Attribute.get_by_id(key) + attr = attr or Attribute.get_by(alias=key, first=True, to_dict=False) if attr is not None: cls.set(attr) return attr @classmethod def set(cls, attr): - cache.set('Field::ID::{0}'.format(attr.id), attr) - cache.set('Field::Name::{0}'.format(attr.name), attr) - cache.set('Field::Alias::{0}'.format(attr.alias), attr) + cache.set(cls.PREFIX_ID.format(attr.id), attr) + cache.set(cls.PREFIX_NAME.format(attr.name), attr) + cache.set(cls.PREFIX_ALIAS.format(attr.alias), attr) @classmethod def clean(cls, attr): - cache.delete('Field::ID::{0}'.format(attr.id)) - cache.delete('Field::Name::{0}'.format(attr.name)) - cache.delete('Field::Alias::{0}'.format(attr.alias)) + cache.delete(cls.PREFIX_ID.format(attr.id)) + cache.delete(cls.PREFIX_NAME.format(attr.name)) + cache.delete(cls.PREFIX_ALIAS.format(attr.alias)) class CITypeCache(object): + PREFIX_ID = "CIType::ID::{0}" + PREFIX_NAME = "CIType::Name::{0}" + PREFIX_ALIAS = "CIType::Alias::{0}" + @classmethod def get(cls, key): if key is None: return - ct = cache.get("CIType::ID::{0}".format(key)) or \ - cache.get("CIType::Name::{0}".format(key)) or \ - cache.get("CIType::Alias::{0}".format(key)) + ct = cache.get(cls.PREFIX_NAME.format(key)) + ct = ct or cache.get(cls.PREFIX_ID.format(key)) + ct = ct or cache.get(cls.PREFIX_ALIAS.format(key)) if ct is None: - ct = CIType.get_by(name=key, first=True, to_dict=False) or \ - CIType.get_by_id(key) or \ - CIType.get_by(alias=key, first=True, to_dict=False) + ct = CIType.get_by(name=key, first=True, to_dict=False) + ct = ct or CIType.get_by_id(key) + ct = ct or CIType.get_by(alias=key, first=True, to_dict=False) if ct is not None: cls.set(ct) return ct @classmethod def set(cls, ct): - cache.set("CIType::Name::{0}".format(ct.name), ct) - cache.set("CIType::ID::{0}".format(ct.id), ct) - cache.set("CIType::Alias::{0}".format(ct.alias), ct) + cache.set(cls.PREFIX_NAME.format(ct.name), ct) + cache.set(cls.PREFIX_ID.format(ct.id), ct) + cache.set(cls.PREFIX_ALIAS.format(ct.alias), ct) @classmethod def clean(cls, key): ct = cls.get(key) if ct is not None: - cache.delete("CIType::Name::{0}".format(ct.name)) - cache.delete("CIType::ID::{0}".format(ct.id)) - cache.delete("CIType::Alias::{0}".format(ct.alias)) + cache.delete(cls.PREFIX_NAME.format(ct.name)) + cache.delete(cls.PREFIX_ID.format(ct.id)) + cache.delete(cls.PREFIX_ALIAS.format(ct.alias)) class RelationTypeCache(object): + PREFIX_ID = "RelationType::ID::{0}" + PREFIX_NAME = "RelationType::Name::{0}" + @classmethod def get(cls, key): if key is None: return - ct = cache.get("RelationType::ID::{0}".format(key)) or \ - cache.get("RelationType::Name::{0}".format(key)) + ct = cache.get(cls.PREFIX_NAME.format(key)) + ct = ct or cache.get(cls.PREFIX_ID.format(key)) if ct is None: ct = RelationType.get_by(name=key, first=True, to_dict=False) or RelationType.get_by_id(key) if ct is not None: @@ -85,15 +96,15 @@ class RelationTypeCache(object): @classmethod def set(cls, ct): - cache.set("RelationType::Name::{0}".format(ct.name), ct) - cache.set("RelationType::ID::{0}".format(ct.id), ct) + cache.set(cls.PREFIX_NAME.format(ct.name), ct) + cache.set(cls.PREFIX_ID.format(ct.id), ct) @classmethod def clean(cls, key): ct = cls.get(key) if ct is not None: - cache.delete("RelationType::Name::{0}".format(ct.name)) - cache.delete("RelationType::ID::{0}".format(ct.id)) + cache.delete(cls.PREFIX_NAME.format(ct.name)) + cache.delete(cls.PREFIX_ID.format(ct.id)) class CITypeAttributeCache(object): @@ -101,13 +112,16 @@ class CITypeAttributeCache(object): key is type_id or type_name """ + PREFIX_ID = "CITypeAttribute::ID::{0}" + PREFIX_NAME = "CITypeAttribute::Name::{0}" + @classmethod def get(cls, key): if key is None: return - attrs = cache.get("CITypeAttribute::Name::{0}".format(key)) \ - or cache.get("CITypeAttribute::ID::{0}".format(key)) + attrs = cache.get(cls.PREFIX_NAME.format(key)) + attrs = attrs or cache.get(cls.PREFIX_ID.format(key)) if not attrs: attrs = CITypeAttribute.get_by(type_id=key, to_dict=False) if not attrs: @@ -122,13 +136,13 @@ class CITypeAttributeCache(object): def set(cls, key, values): ci_type = CITypeCache.get(key) if ci_type is not None: - cache.set("CITypeAttribute::ID::{0}".format(ci_type.id), values) - cache.set("CITypeAttribute::Name::{0}".format(ci_type.name), values) + cache.set(cls.PREFIX_ID.format(ci_type.id), values) + cache.set(cls.PREFIX_NAME.format(ci_type.name), values) @classmethod def clean(cls, key): ci_type = CITypeCache.get(key) attrs = cls.get(key) if attrs is not None and ci_type: - cache.delete("CITypeAttribute::ID::{0}".format(ci_type.id)) - cache.delete("CITypeAttribute::Name::{0}".format(ci_type.name)) + cache.delete(cls.PREFIX_ID.format(ci_type.id)) + cache.delete(cls.PREFIX_NAME.format(ci_type.name)) diff --git a/api/lib/cmdb/ci.py b/api/lib/cmdb/ci.py index e62e675..ffaabdb 100644 --- a/api/lib/cmdb/ci.py +++ b/api/lib/cmdb/ci.py @@ -167,10 +167,10 @@ class CIManager(object): unique_key = AttributeCache.get(ci_type.unique_id) or abort(400, 'illegality unique attribute') - unique_value = ci_dict.get(unique_key.name) or \ - ci_dict.get(unique_key.alias) or \ - ci_dict.get(unique_key.id) or \ - abort(400, '{0} missing'.format(unique_key.name)) + unique_value = ci_dict.get(unique_key.name) + unique_value = unique_value or ci_dict.get(unique_key.alias) + unique_value = unique_value or ci_dict.get(unique_key.id) + unique_value = unique_value or abort(400, '{0} missing'.format(unique_key.name)) existed = cls.ci_is_exist(unique_key, unique_value) if existed is not None: @@ -425,8 +425,8 @@ class CIRelationManager(object): def get_second_cis(self, first_ci_id, relation_type_id=None, page=1, per_page=None, **kwargs): second_cis = db.session.query(CI.id).filter(CI.deleted.is_(False)).join( - CIRelation, CIRelation.second_ci_id == CI.id).filter( - CIRelation.first_ci_id == first_ci_id) + CIRelation, CIRelation.second_ci_id == CI.id).filter( + CIRelation.first_ci_id == first_ci_id) if relation_type_id is not None: second_cis = second_cis.filter(CIRelation.relation_type_id == relation_type_id) diff --git a/api/lib/cmdb/ci_type.py b/api/lib/cmdb/ci_type.py index c4b2b23..f0b4e29 100644 --- a/api/lib/cmdb/ci_type.py +++ b/api/lib/cmdb/ci_type.py @@ -1,21 +1,21 @@ # -*- coding:utf-8 -*- -from flask import current_app from flask import abort +from flask import current_app -from api.models.cmdb import CITypeAttribute -from api.models.cmdb import CIType -from api.models.cmdb import CITypeGroup -from api.models.cmdb import CITypeGroupItem -from api.models.cmdb import CITypeRelation -from api.models.cmdb import CITypeAttributeGroup -from api.models.cmdb import CITypeAttributeGroupItem +from api.lib.cmdb.attribute import AttributeManager from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.cache import CITypeAttributeCache from api.lib.cmdb.cache import CITypeCache -from api.lib.cmdb.attribute import AttributeManager from api.lib.decorator import kwargs_required +from api.models.cmdb import CIType +from api.models.cmdb import CITypeAttribute +from api.models.cmdb import CITypeAttributeGroup +from api.models.cmdb import CITypeAttributeGroupItem +from api.models.cmdb import CITypeGroup +from api.models.cmdb import CITypeGroupItem +from api.models.cmdb import CITypeRelation class CITypeManager(object): @@ -54,8 +54,7 @@ class CITypeManager(object): unique_key = kwargs.pop("unique_key", None) unique_key = AttributeCache.get(unique_key) or abort(404, "Unique key is not defined") - CIType.get_by(name=kwargs['name'], first=True) and \ - abort(404, "CIType <{0}> is already existed".format(kwargs.get("name"))) + CIType.get_by(name=kwargs['name']) and abort(404, "CIType <{0}> is already existed".format(kwargs.get("name"))) kwargs["alias"] = kwargs["name"] if not kwargs.get("alias") else kwargs["alias"] @@ -349,8 +348,8 @@ class CITypeAttributeGroupManager(object): :param attr_order: :return: """ - existed = CITypeAttributeGroup.get_by(type_id=type_id, name=name, first=True, to_dict=False) \ - or CITypeAttributeGroup.create(type_id=type_id, name=name, order=group_order) + existed = CITypeAttributeGroup.get_by(type_id=type_id, name=name, first=True, to_dict=False) + existed = existed or CITypeAttributeGroup.create(type_id=type_id, name=name, order=group_order) existed.update(order=group_order) attr_order = dict(attr_order) current_app.logger.info(attr_order) @@ -382,7 +381,7 @@ class CITypeAttributeGroupManager(object): @staticmethod def delete(group_id): group = CITypeAttributeGroup.get_by_id(group_id) \ - or abort(404, "AttributeGroup <{0}> does not exist".format(group_id)) + or abort(404, "AttributeGroup <{0}> does not exist".format(group_id)) group.soft_delete() items = CITypeAttributeGroupItem.get_by(group_id=group_id, to_dict=False) diff --git a/api/lib/cmdb/const.py b/api/lib/cmdb/const.py index f8bcbc3..a55d665 100644 --- a/api/lib/cmdb/const.py +++ b/api/lib/cmdb/const.py @@ -5,19 +5,19 @@ import datetime import six from markupsafe import escape +from api.lib.cmdb.cache import AttributeCache from api.models.cmdb import Attribute -from api.models.cmdb import TextChoice -from api.models.cmdb import FloatChoice -from api.models.cmdb import IntegerChoice -from api.models.cmdb import CIValueText -from api.models.cmdb import CIValueInteger -from api.models.cmdb import CIValueFloat -from api.models.cmdb import CIValueDateTime from api.models.cmdb import CIIndexValueDateTime from api.models.cmdb import CIIndexValueFloat from api.models.cmdb import CIIndexValueInteger from api.models.cmdb import CIIndexValueText -from api.lib.cmdb.cache import AttributeCache +from api.models.cmdb import CIValueDateTime +from api.models.cmdb import CIValueFloat +from api.models.cmdb import CIValueInteger +from api.models.cmdb import CIValueText +from api.models.cmdb import FloatChoice +from api.models.cmdb import IntegerChoice +from api.models.cmdb import TextChoice def string2int(x): @@ -144,5 +144,6 @@ class PermEnum(object): class RoleEnum(object): CONFIG = "admin" + CMDB_QUEUE = "cmdb_async" REDIS_PREFIX = "CMDB_CI" diff --git a/api/lib/cmdb/history.py b/api/lib/cmdb/history.py index 2116370..ed2ba6f 100644 --- a/api/lib/cmdb/history.py +++ b/api/lib/cmdb/history.py @@ -1,22 +1,20 @@ # -*- coding:utf-8 -*- -from flask import g from flask import abort - +from flask import g from api.extensions import db -from api.models.cmdb import Attribute -from api.models.cmdb import OperationRecord -from api.models.cmdb import AttributeHistory -from api.models.cmdb import CIRelationHistory -from api.models.account import UserCache from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.cache import RelationTypeCache +from api.models.account import UserCache +from api.models.cmdb import Attribute +from api.models.cmdb import AttributeHistory +from api.models.cmdb import CIRelationHistory +from api.models.cmdb import OperationRecord class AttributeHistoryManger(object): - @staticmethod def get_records(start, end, username, page, page_size): records = db.session.query(OperationRecord).filter(OperationRecord.deleted.is_(False)) @@ -113,7 +111,6 @@ class AttributeHistoryManger(object): class CIRelationHistoryManager(object): - @staticmethod def add(rel_obj, operate_type=CIRelationHistory.ADD): record = OperationRecord.create(uid=g.user.uid) diff --git a/api/lib/cmdb/preference.py b/api/lib/cmdb/preference.py index 0fabe64..ae18acd 100644 --- a/api/lib/cmdb/preference.py +++ b/api/lib/cmdb/preference.py @@ -2,22 +2,21 @@ import six import toposort -from flask import g from flask import abort +from flask import g from api.extensions import db +from api.lib.cmdb.attribute import AttributeManager from api.lib.cmdb.cache import AttributeCache -from api.lib.cmdb.cache import CITypeCache from api.lib.cmdb.cache import CITypeAttributeCache +from api.lib.cmdb.cache import CITypeCache +from api.models.cmdb import CITypeAttribute +from api.models.cmdb import PreferenceRelationView from api.models.cmdb import PreferenceShowAttributes from api.models.cmdb import PreferenceTreeView -from api.models.cmdb import PreferenceRelationView -from api.models.cmdb import CITypeAttribute -from api.lib.cmdb.attribute import AttributeManager class PreferenceManager(object): - @staticmethod def get_types(instance=False, tree=False): types = db.session.query(PreferenceShowAttributes.type_id).filter( diff --git a/api/lib/cmdb/search.py b/api/lib/cmdb/search.py index df46d9f..3f3a12c 100644 --- a/api/lib/cmdb/search.py +++ b/api/lib/cmdb/search.py @@ -8,7 +8,6 @@ import time from flask import current_app from api.extensions import db -from api.lib.utils import handle_arg_list from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.cache import CITypeCache from api.lib.cmdb.ci import CIManager @@ -17,6 +16,7 @@ from api.lib.cmdb.const import TableMap from api.lib.cmdb.query_sql import FACET_QUERY from api.lib.cmdb.query_sql import QUERY_CI_BY_ATTR_NAME from api.lib.cmdb.query_sql import QUERY_CI_BY_TYPE +from api.lib.utils import handle_arg_list from api.models.cmdb import Attribute from api.models.cmdb import CI diff --git a/api/lib/cmdb/value.py b/api/lib/cmdb/value.py index af16f39..c320644 100644 --- a/api/lib/cmdb/value.py +++ b/api/lib/cmdb/value.py @@ -2,18 +2,17 @@ import markupsafe - from flask import abort from api.extensions import db -from api.lib.utils import handle_arg_list -from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.attribute import AttributeManager -from api.lib.cmdb.const import type_map -from api.lib.cmdb.const import TableMap +from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.const import ExistPolicy from api.lib.cmdb.const import OperateType +from api.lib.cmdb.const import TableMap +from api.lib.cmdb.const import type_map from api.lib.cmdb.history import AttributeHistoryManger +from api.lib.utils import handle_arg_list from api.models.cmdb import Attribute @@ -87,10 +86,10 @@ class AttributeValueManager(object): @staticmethod def __check_is_unique(value_table, attr_id, ci_id, value): - db.session.query(value_table.attr_id).filter( + existed = db.session.query(value_table.attr_id).filter( value_table.attr_id == attr_id).filter(value_table.deleted.is_(False)).filter( - value_table.value == value).filter(value_table.ci_id != ci_id).first() \ - and abort(400, "attribute <{0}> value {1} must be unique".format(attr_id, value)) + value_table.value == value).filter(value_table.ci_id != ci_id).first() + existed and abort(400, "attribute <{0}> value {1} must be unique".format(attr_id, value)) def _validate(self, attr, value, value_table, ci_id): v = self.__deserialize_value(attr.value_type, value) @@ -131,7 +130,7 @@ class AttributeValueManager(object): value_list = handle_arg_list(value) if attr.is_list else [value] if not isinstance(value, list): value_list = [value] - + for v in value_list: v = self._validate(attr, v, value_table, ci_id) if not v and attr.value_type != Attribute.TEXT: diff --git a/api/lib/http_cli.py b/api/lib/http_cli.py index 6c59777..4d9e519 100644 --- a/api/lib/http_cli.py +++ b/api/lib/http_cli.py @@ -4,10 +4,10 @@ import hashlib import requests -from future.moves.urllib.parse import urlparse from flask import abort -from flask import g from flask import current_app +from flask import g +from future.moves.urllib.parse import urlparse def build_api_key(path, params): diff --git a/api/lib/mail.py b/api/lib/mail.py index 0fbf25d..5c5c785 100644 --- a/api/lib/mail.py +++ b/api/lib/mail.py @@ -1,40 +1,40 @@ # -*- coding:utf-8 -*- -from flask import current_app - -from email.mime.multipart import MIMEMultipart -from email.mime.text import MIMEText -from email.header import Header -from email.mime.image import MIMEImage import smtplib import time from email import Utils +from email.header import Header +from email.mime.image import MIMEImage +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText + +from flask import current_app def send_mail(sender, receiver, subject, content, ctype="html", pics=()): """subject and body are unicode objects""" if not sender: sender = current_app.config.get("DEFAULT_MAIL_SENDER") - smtpserver = current_app.config.get("MAIL_SERVER") + smtp_server = current_app.config.get("MAIL_SERVER") if ctype == "html": msg = MIMEText(content, 'html', 'utf-8') else: msg = MIMEText(content, 'plain', 'utf-8') if len(pics) != 0: - msgRoot = MIMEMultipart('related') - msgText = MIMEText(content, 'html', 'utf-8') - msgRoot.attach(msgText) + msg_root = MIMEMultipart('related') + msg_text = MIMEText(content, 'html', 'utf-8') + msg_root.attach(msg_text) i = 1 for pic in pics: fp = open(pic, "rb") image = MIMEImage(fp.read()) fp.close() image.add_header('Content-ID', '' % i) - msgRoot.attach(image) + msg_root.attach(image) i += 1 - msg = msgRoot + msg = msg_root msg['Subject'] = Header(subject, 'utf-8') msg['From'] = sender @@ -43,7 +43,9 @@ def send_mail(sender, receiver, subject, content, ctype="html", pics=()): msg['date'] = time.strftime('%a, %d %b %Y %H:%M:%S %z') smtp = smtplib.SMTP() - smtp.connect(smtpserver, 25) - # smtp.login(username, password) + smtp.connect(smtp_server, 25) + username, password = current_app.config.get("MAIL_USERNAME"), current_app.config.get("MAIL_PASSWORD") + if username and password: + smtp.login(username, password) smtp.sendmail(sender, receiver, msg.as_string()) smtp.quit() diff --git a/api/lib/perm/acl.py b/api/lib/perm/acl/acl.py similarity index 100% rename from api/lib/perm/acl.py rename to api/lib/perm/acl/acl.py diff --git a/api/lib/perm/auth.py b/api/lib/perm/auth.py index e1637f4..d28d3fa 100644 --- a/api/lib/perm/auth.py +++ b/api/lib/perm/auth.py @@ -4,11 +4,11 @@ from functools import wraps import jwt +from flask import abort from flask import current_app +from flask import g from flask import request from flask import session -from flask import g -from flask import abort from flask_login import login_user from api.models.account import User @@ -54,7 +54,7 @@ def _auth_with_token(): return True except jwt.ExpiredSignatureError: return False - except (jwt.InvalidTokenError, Exception) as e: + except (jwt.InvalidTokenError, Exception): return False diff --git a/api/lib/utils.py b/api/lib/utils.py index dd00fb1..7031f84 100644 --- a/api/lib/utils.py +++ b/api/lib/utils.py @@ -1,7 +1,7 @@ # -*- coding:utf-8 -*- -import six import redis +import six from flask import current_app @@ -52,7 +52,7 @@ class RedisHandler(object): try: value = self.r.hmget(self.prefix, key_ids) except Exception as e: - current_app.logger.error("get redis error, %s" % str(e)) + current_app.logger.error("get redis error, {0}".format(str(e))) return return value @@ -60,7 +60,7 @@ class RedisHandler(object): try: self.r.hmset(self.prefix, obj) except Exception as e: - current_app.logger.error("set redis error, %s" % str(e)) + current_app.logger.error("set redis error, {0}".format(str(e))) def add(self, obj): self._set(obj) @@ -69,6 +69,6 @@ class RedisHandler(object): try: ret = self.r.hdel(self.prefix, key_id) if not ret: - current_app.logger.warn("[%d] is not in redis" % key_id) + current_app.logger.warn("[%d] is not in redis".format(key_id)) except Exception as e: - current_app.logger.error("delete redis key error, %s" % str(e)) + current_app.logger.error("delete redis key error, {0}".format(str(e))) diff --git a/api/models/__init__.py b/api/models/__init__.py index fabbe66..c10c68e 100644 --- a/api/models/__init__.py +++ b/api/models/__init__.py @@ -3,3 +3,4 @@ from .account import User from .cmdb import * +from .acl import * diff --git a/api/models/account.py b/api/models/account.py index 15bb04c..4311bbd 100644 --- a/api/models/account.py +++ b/api/models/account.py @@ -4,16 +4,17 @@ import copy import hashlib from datetime import datetime -import six from flask import current_app from flask_sqlalchemy import BaseQuery -from api.extensions import db from api.extensions import cache +from api.extensions import db from api.lib.database import CRUDModel class UserQuery(BaseQuery): + def _join(self, *args, **kwargs): + super(UserQuery, self)._join(*args, **kwargs) def authenticate(self, login, password): user = self.filter(db.or_(User.username == login, @@ -60,9 +61,6 @@ class User(CRUDModel): __bind_key__ = "user" query_class = UserQuery - ADMIN = 1 - OP = 2 - uid = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(32), unique=True) nickname = db.Column(db.String(20), nullable=True) @@ -79,6 +77,7 @@ class User(CRUDModel): has_logined = db.Column(db.Boolean, default=False) wx_id = db.Column(db.String(32)) avatar = db.Column(db.String(128)) + is_admin = db.Column(db.Boolean, default=False) def __str__(self): return self.username @@ -108,91 +107,34 @@ class User(CRUDModel): return False return self.password == password - @property - def roles(self): - urs = db.session.query(UserRole.rid).filter( - UserRole.uid == self.uid).all() - return [x.rid for x in urs] - - @property - def rolenames(self): - roles = list() - for rid in self.roles: - role = db.session.query(Role).filter(Role.rid == rid).first() - roles.append(role.role_name) - return roles - - @property - def is_admin(self): - return self.ADMIN in self.roles - - -class Role(CRUDModel): - __tablename__ = 'roles' - __bind_key__ = "user" - - rid = db.Column(db.Integer, primary_key=True, autoincrement=True) - role_name = db.Column(db.String(64), nullable=False, unique=True) - - -class UserRole(CRUDModel): - __tablename__ = 'users_roles' - __bind_key__ = "user" - - uid = db.Column(db.Integer, db.ForeignKey('users.uid'), primary_key=True) - rid = db.Column(db.Integer, db.ForeignKey('roles.rid'), primary_key=True) - class UserCache(object): + PREFIX_ID = "User::uid::{0}" + PREFIX_NAME = "User::username::{0}" + PREFIX_NICK = "User::nickname::{0}" + @classmethod def get(cls, key): - user = cache.get("User::uid::%s" % key) or \ - cache.get("User::username::%s" % key) or \ - cache.get("User::nickname::%s" % key) + user = cache.get(cls.PREFIX_ID.format(key)) or \ + cache.get(cls.PREFIX_NAME.format(key)) or \ + cache.get(cls.PREFIX_NICK.format(key)) if not user: user = User.query.get(key) or \ - User.query.get_by_username(key) or \ - User.query.get_by_nickname(key) + User.query.get_by_username(key) or \ + User.query.get_by_nickname(key) if user: cls.set(user) + return user @classmethod def set(cls, user): - cache.set("User::uid::%s" % user.uid, user) - cache.set("User::username::%s" % user.username, user) - cache.set("User::nickname::%s" % user.nickname, user) + cache.set(cls.PREFIX_ID.format(user.uid, user)) + cache.set(cls.PREFIX_NAME.format(user.username, user)) + cache.set(cls.PREFIX_NICK.format(user.nickname, user)) @classmethod def clean(cls, user): - cache.delete("User::uid::%s" % user.uid) - cache.delete("User::username::%s" % user.username) - cache.delete("User::nickname::%s" % user.nickname) - - -class RoleCache(object): - @classmethod - def get(cls, rid): - role = None - if isinstance(rid, six.integer_types): - role = cache.get("Role::rid::%s" % rid) - if not role: - role = db.session.query(Role).filter(Role.rid == rid).first() - cls.set(role) - elif isinstance(rid, six.string_types): - role = cache.get("Role::role_name::%s" % rid) - if not role: - role = db.session.query(Role).filter( - Role.role_name == rid).first() - cls.set(role) - return role - - @classmethod - def set(cls, role): - cache.set("Role::rid::%s" % role.rid, role) - cache.set("Role::role_name::%s" % role.role_name, role) - - @classmethod - def clean(cls, role): - cache.delete("Role::rid::%s" % role.rid, role) - cache.delete("Role::role_name::%s" % role.role_name, role) + cache.delete(cls.PREFIX_ID.format(user.uid)) + cache.delete(cls.PREFIX_NAME.format(user.username)) + cache.delete(cls.PREFIX_NICK.format(user.nickname)) diff --git a/api/models/cmdb.py b/api/models/cmdb.py index 37251c5..c9d4834 100644 --- a/api/models/cmdb.py +++ b/api/models/cmdb.py @@ -3,8 +3,8 @@ import datetime -from api.lib.database import Model from api.extensions import db +from api.lib.database import Model # template @@ -57,7 +57,7 @@ class CITypeRelation(Model): class Attribute(Model): __tablename__ = "c_attributes" - + INT = "0" FLOAT = "1" TEXT = "2" @@ -76,8 +76,8 @@ class Attribute(Model): is_link = db.Column(db.Boolean, default=False) is_password = db.Column(db.Boolean, default=False) is_sortable = db.Column(db.Boolean, default=False) - - + + class CITypeAttribute(Model): __tablename__ = "c_ci_type_attributes" @@ -171,7 +171,7 @@ class CIIndexValueInteger(Model): ci = db.relationship("CI", backref="c_value_index_integers.ci_id") attr = db.relationship("Attribute", backref="c_value_index_integers.attr_id") - __table_args__ = (db.Index("integer_attr_value_index", "attr_id", "value"), ) + __table_args__ = (db.Index("integer_attr_value_index", "attr_id", "value"),) class CIIndexValueFloat(Model): @@ -184,7 +184,7 @@ class CIIndexValueFloat(Model): ci = db.relationship("CI", backref="c_value_index_floats.ci_id") attr = db.relationship("Attribute", backref="c_value_index_floats.attr_id") - __table_args__ = (db.Index("float_attr_value_index", "attr_id", "value"), ) + __table_args__ = (db.Index("float_attr_value_index", "attr_id", "value"),) class CIIndexValueText(Model): @@ -197,7 +197,7 @@ class CIIndexValueText(Model): ci = db.relationship("CI", backref="c_value_index_texts.ci_id") attr = db.relationship("Attribute", backref="c_value_index_texts.attr_id") - __table_args__ = (db.Index("text_attr_value_index", "attr_id", "value"), ) + __table_args__ = (db.Index("text_attr_value_index", "attr_id", "value"),) class CIIndexValueDateTime(Model): @@ -210,7 +210,7 @@ class CIIndexValueDateTime(Model): ci = db.relationship("CI", backref="c_value_index_datetime.ci_id") attr = db.relationship("Attribute", backref="c_value_index_datetime.attr_id") - __table_args__ = (db.Index("datetime_attr_value_index", "attr_id", "value"), ) + __table_args__ = (db.Index("datetime_attr_value_index", "attr_id", "value"),) class CIValueInteger(Model): diff --git a/api/tasks/test.py b/api/tasks/test.py index a19d362..d920ad1 100644 --- a/api/tasks/test.py +++ b/api/tasks/test.py @@ -1,8 +1,9 @@ # -*- coding:utf-8 -*- -from api.extensions import celery from flask import current_app +from api.extensions import celery + @celery.task(queue="ticket_web") def test_task(): diff --git a/api/views/account.py b/api/views/account.py index f6d7dbc..21cc2f1 100644 --- a/api/views/account.py +++ b/api/views/account.py @@ -3,15 +3,15 @@ import datetime import jwt -from flask import request -from flask import current_app from flask import abort +from flask import current_app +from flask import request from flask_login import login_user, logout_user -from api.resource import APIView from api.lib.decorator import args_required from api.lib.perm.auth import auth_abandoned from api.models.account import User +from api.resource import APIView class LoginView(APIView): diff --git a/api/views/cmdb/attribute.py b/api/views/cmdb/attribute.py index b09e3df..8089aae 100644 --- a/api/views/cmdb/attribute.py +++ b/api/views/cmdb/attribute.py @@ -1,19 +1,18 @@ # -*- coding:utf-8 -*- -from flask import request from flask import abort from flask import current_app +from flask import request -from api.resource import APIView -from api.lib.perm.acl import role_required -from api.lib.cmdb.const import RoleEnum from api.lib.cmdb.attribute import AttributeManager +from api.lib.cmdb.const import RoleEnum from api.lib.decorator import args_required -from api.lib.utils import handle_arg_list +from api.lib.perm.acl.acl import role_required from api.lib.utils import get_page from api.lib.utils import get_page_size - +from api.lib.utils import handle_arg_list +from api.resource import APIView class AttributeSearchView(APIView): @@ -72,4 +71,4 @@ class AttributeView(APIView): @role_required(RoleEnum.CONFIG) def delete(self, attr_id): attr_name = AttributeManager.delete(attr_id) - return self. jsonify(message="attribute {0} deleted".format(attr_name)) + return self.jsonify(message="attribute {0} deleted".format(attr_name)) diff --git a/api/views/cmdb/ci.py b/api/views/cmdb/ci.py index 0f6bd16..210f86c 100644 --- a/api/views/cmdb/ci.py +++ b/api/views/cmdb/ci.py @@ -7,14 +7,14 @@ from flask import abort from flask import current_app from flask import request -from api.lib.perm.acl import has_perm_from_args -from api.lib.cmdb.const import ResourceType, PermEnum from api.lib.cmdb.cache import CITypeCache from api.lib.cmdb.ci import CIManager from api.lib.cmdb.const import ExistPolicy +from api.lib.cmdb.const import ResourceType, PermEnum from api.lib.cmdb.const import RetKey from api.lib.cmdb.search import Search from api.lib.cmdb.search import SearchError +from api.lib.perm.acl.acl import has_perm_from_args from api.lib.perm.auth import auth_abandoned from api.lib.utils import get_page from api.lib.utils import get_page_size diff --git a/api/views/cmdb/ci_type.py b/api/views/cmdb/ci_type.py index 14b6153..554655d 100644 --- a/api/views/cmdb/ci_type.py +++ b/api/views/cmdb/ci_type.py @@ -5,17 +5,17 @@ from flask import abort from flask import current_app from flask import request -from api.resource import APIView -from api.lib.perm.acl import role_required -from api.lib.cmdb.const import RoleEnum from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.cache import CITypeCache -from api.lib.cmdb.ci_type import CITypeAttributeManager -from api.lib.cmdb.ci_type import CITypeManager -from api.lib.cmdb.ci_type import CITypeGroupManager from api.lib.cmdb.ci_type import CITypeAttributeGroupManager +from api.lib.cmdb.ci_type import CITypeAttributeManager +from api.lib.cmdb.ci_type import CITypeGroupManager +from api.lib.cmdb.ci_type import CITypeManager +from api.lib.cmdb.const import RoleEnum from api.lib.decorator import args_required +from api.lib.perm.acl.acl import role_required from api.lib.utils import handle_arg_list +from api.resource import APIView class CITypeView(APIView): @@ -128,7 +128,7 @@ class CITypeAttributeView(APIView): def post(self, type_id=None): attr_id_list = handle_arg_list(request.values.get("attr_id")) params = request.values - params.pop("attr_id", "") + params.pop("attr_id", "") CITypeAttributeManager.add(type_id, attr_id_list, **params) return self.jsonify(attributes=attr_id_list) diff --git a/api/views/cmdb/ci_type_relation.py b/api/views/cmdb/ci_type_relation.py index 613d1ba..ead8ed2 100644 --- a/api/views/cmdb/ci_type_relation.py +++ b/api/views/cmdb/ci_type_relation.py @@ -3,10 +3,10 @@ from flask import request -from api.lib.perm.acl import role_required -from api.lib.cmdb.const import RoleEnum from api.lib.cmdb.ci_type import CITypeRelationManager +from api.lib.cmdb.const import RoleEnum from api.lib.decorator import args_required +from api.lib.perm.acl.acl import role_required from api.resource import APIView diff --git a/api/views/cmdb/preference.py b/api/views/cmdb/preference.py index d09437f..e54b7d4 100644 --- a/api/views/cmdb/preference.py +++ b/api/views/cmdb/preference.py @@ -3,14 +3,13 @@ from flask import request -from api.resource import APIView -from api.lib.perm.acl import has_perm_from_args +from api.lib.cmdb.ci_type import CITypeManager from api.lib.cmdb.const import ResourceType, PermEnum from api.lib.cmdb.preference import PreferenceManager -from api.lib.cmdb.ci import CIManager -from api.lib.cmdb.ci_type import CITypeManager from api.lib.decorator import args_required +from api.lib.perm.acl.acl import has_perm_from_args from api.lib.utils import handle_arg_list +from api.resource import APIView class PreferenceShowCITypesView(APIView): diff --git a/api/views/cmdb/relation_type.py b/api/views/cmdb/relation_type.py index df96302..9ff310b 100644 --- a/api/views/cmdb/relation_type.py +++ b/api/views/cmdb/relation_type.py @@ -1,14 +1,14 @@ # -*- coding:utf-8 -*- -from flask import request from flask import abort +from flask import request -from api.resource import APIView -from api.lib.perm.acl import role_required from api.lib.cmdb.const import RoleEnum -from api.lib.decorator import args_required from api.lib.cmdb.relation_type import RelationTypeManager +from api.lib.decorator import args_required +from api.lib.perm.acl.acl import role_required +from api.resource import APIView class RelationTypeView(APIView): diff --git a/api/views/permission.py b/api/views/permission.py index 70cb5b2..3eb67d8 100644 --- a/api/views/permission.py +++ b/api/views/permission.py @@ -5,8 +5,8 @@ from flask import session from flask_login import current_user from api.lib.decorator import args_required -from api.lib.perm.acl import ACLManager -from api.lib.perm.acl import validate_permission +from api.lib.perm.acl.acl import ACLManager +from api.lib.perm.acl.acl import validate_permission from api.resource import APIView