def put(bag): data = {"type": bag["type"]} del bag["type"] if '_created' in bag: del bag["_created"] if '_deleted' in bag: del bag["_deleted"] table_name = data["type"] table = getattr(db, table_name) if table is None or not issubclass(table, (db.Base, db.CouchSync)): raise CbsException(TABLE_NOT_FOUND) for key in bag: data[key] = bag[key] # del_columns(data) for column in table.metadata.tables.get(table_name.lower()).columns._data: nullable = table.metadata.tables.get( table_name.lower()).columns._data[column].nullable if not nullable and not column.startswith( "_") and not column == "entry_user_id" and column not in data: raise CbsException(KEY_ERROR, MESSAGE.get(KEY_ERROR).format(column)) elif not column.startswith( "_") and not column == "entry_user_id" and column not in data: data[column] = None pg_db = PostgresDatabase() _id, _rev = pg_db.store(data, new_edits=True) return {"ok": True, "id": _id, "rev": _rev}
def delete(bag): if 'company_id' in g.session and not is_admin(): bag['company_id'] = g.session['company_id'] # if not is_admin() and "company_id" not in bag: # raise CbsException(USER_NO_ACCESS) table_name = bag["type"] table = getattr(db, table_name) if table is None or not issubclass(table, (db.Base, db.CouchSync)): raise CbsException(TABLE_NOT_FOUND) if not is_admin(): item_query = g.tran.query(table).filter_by(_deleted="infinity", _id=bag["_id"]) if table == db.Companies: item_query = item_query.filter(table._id == bag["company_id"], table.user_id == g.user.id) if issubclass(table, db.CompanySync): item_query = item_query.filter( table.company_id == bag["company_id"]) elif table == db.Companyemployees: item_query = item_query.filter(table.user_id == bag["user_id"]) if issubclass(table, db.CompanySync): item_query = item_query.filter( table.company_id == bag["company_id"]) else: item_query = item_query.first() if item_query is None: raise CbsException(USER_NO_ACCESS) pg_db = PostgresDatabase() _id, _rev = pg_db.remove(bag["_id"], bag["_rev"]) return {"ok": True, "id": _id, "rev": _rev}
def saveapproval(self, bag): if '_created' in bag: del bag["_created"] if '_deleted' in bag: del bag["_deleted"] if 'date' not in bag['data']: bag["data"]['date'] = str(datetime.now()) if '_id' in bag: query = g.tran.query(db.Document).filter_by(_id=bag['_id']) \ .filter(db.Document.document_status != 'committed') document = query.first() if document is None: raise CbsException(USER_NO_ACCESS) pg_db = PostgresDatabase() bag['type'] = 'Document' bag['document_status'] = 'draft' if len(g.user.roles_id) > 0: bag['approval']['approval_roles'] = [] for role_id in bag['approval']['roles_id']: bag['approval']['approval_roles'].append({ 'role_id': role_id }) _id, _rev = pg_db.store(bag, new_edits=True) return {"ok": True, "id": _id, "rev": _rev}
def save(self, bag): if '_created' in bag: del bag["_created"] if '_deleted' in bag: del bag["_deleted"] if 'date' not in bag['data']: bag["data"]['date'] = str(datetime.now()) if '_id' in bag: query = g.tran.query(db.Document).filter_by(_id=bag['_id']) \ .filter(db.Document.data.contains(type_coerce({"user_id": g.user.id}, JSONB)), db.Document.document_status != 'committed') document = query.first() if document is None: raise CbsException(USER_NO_ACCESS) if g.user.roles_id is None: raise CbsException(GENERIC_ERROR, u'Вам необходимо получить права') else: pg_db = PostgresDatabase() bag['type'] = 'Document' bag['document_status'] = 'draft' bag['data']['user_id'] = g.user.id if len(g.user.roles_id) > 0: bag['approval']['approval_roles'] = [] for role_id in bag['approval']['roles_id']: bag['approval']['approval_roles'].append({ 'role_id': role_id }) _id, _rev = pg_db.store(bag, new_edits=True) return {"ok": True, "id": _id, "rev": _rev}
def database_changes(dbname): args = flask.request.args heartbeat = args.get('heartbeat', 10000) since = json.loads(args.get('since', '0')) feed = args.get('feed', 'normal') style = args.get('style', 'all_docs') filter = args.get('filter', None) limit = args.get('limit', None) timeout = int(args.get('timeout', 25000)) db = PostgresDatabase() changes, last_seq = db.changes(since, feed, style, filter, limit, timeout / 1000) return make_response(200, {'last_seq': last_seq, 'results': changes})
def remove(bag): table_name = bag["type"] table = getattr(db, table_name) if table is None or not issubclass(table, (db.Base, db.CouchSync)): raise CbsException(TABLE_NOT_FOUND) if not is_admin(): item_query = g.tran.query(table).filter_by(_deleted="infinity", _id=bag["_id"]) item_query = item_query.first() if item_query is None: raise CbsException(USER_NO_ACCESS) pg_db = PostgresDatabase() _id, _rev = pg_db.remove(bag["_id"], bag["_rev"]) return {"ok": True, "id": _id, "rev": _rev}
def get(): if appconf.DB != dbname: return flask.abort(404, '%s missed' % dbname) return make_response(200, PostgresDatabase().info())
def all_docs(dbname): args = {} for a in flask.request.args: args[a] = json.loads(flask.request.args[a]) db = PostgresDatabase() return make_response(200, db.all_docs(**args))
def database_ensure_full_commit(dbname): db = PostgresDatabase() return make_response(201, db.ensure_full_commit())
def database_bulk_docs(dbname): db = PostgresDatabase() return make_response(201, db.bulk_docs(**flask.request.get_json()))
def database_revs_diff(dbname): db = PostgresDatabase() revs = db.revs_diff(flask.request.json) return make_response(200, revs)
def document(dbname, docid): def head(): return get() def get(): if flask.request.args.get('open_revs'): open_revs = json.loads(flask.request.args['open_revs']) ret = [] for rev in open_revs: doc = db.load(docid, rev=rev, revs=flask.request.args.get('revs', False)) ret.append(doc) return make_response(200, ret) else: doc = db.load(docid, rev=flask.request.args.get('rev', None), revs=flask.request.args.get('revs', False)) return make_response(200, doc) def put(): rev = flask.request.args.get('rev') new_edits = json.loads(flask.request.args.get('new_edits', 'true')) if flask.request.mimetype == 'application/json': doc = flask.request.get_json() elif flask.request.mimetype == 'multipart/related': parts = parse_multipart_data( flask.request.stream, flask.request.mimetype_params['boundary']) # CouchDB has an agreement, that document goes before attachments # which simplifies processing logic and reduces footprint headers, body = next(parts) assert headers['Content-Type'] == 'application/json' doc = json.loads(body.decode()) # We have to inject revision into doc there to correct compute # revpos field for attachments doc.setdefault('_rev', rev) for headers, body in parts: params = werkzeug.http.parse_options_header( headers['Content-Disposition'])[1] fname = params['filename'] ctype = headers['Content-Type'] db.add_attachment(doc, fname, body, ctype) else: # mimics to CouchDB response in case of unsupported mime-type return flask.abort(400) doc['_id'] = docid idx, rev = db.store(doc, rev, new_edits) return make_response(201, {'ok': True, 'id': idx, 'rev': rev}) def delete(): idx, rev = db.remove(docid, flask.request.args.get('rev', None)) return make_response(201, {'ok': True, 'id': idx, 'rev': rev}) db = PostgresDatabase() return locals()[flask.request.method.lower()]()
def approve(self, bag, approve, comment): roles_filter = [] for role_id in g.user.roles_id: roles_filter.append(db.Document.approval.contains(type_coerce({'approval_roles': [{"role_id": role_id}]}, JSONB))) query = g.tran.query(db.Document).filter_by(_id=bag[ID] if ID in bag else bag['_id'], _deleted='infinity') \ .filter(or_(and_(db.Document.document_status == "approval", or_(*roles_filter)), and_(db.Document.document_status == "approved", db.Document.data.contains(type_coerce({'executor_id': g.user.id}, JSONB))), and_(db.Document.document_status == 'draft', db.Document.data.contains(type_coerce({'user_id': g.user.id}, JSONB))))) document = query.first() if document is None: raise CbsException(USER_NO_ACCESS) doc_data = orm_to_json(document) del doc_data["_created"] del doc_data["_deleted"] del doc_data["entry_user_id"] if bag['document_status'] == 'draft' and doc_data['document_status'] == 'draft': doc_data['document_status'] = 'approval'if \ 'required' in doc_data['approval'] and doc_data['approval']['required'] == True else 'approved' pg_db = PostgresDatabase() doc_data['type'] = 'Document' _id, _rev = pg_db.store(doc_data) return {"id": _id, "rev": _rev} elif bag['document_status'] == 'approval' and doc_data['document_status'] == 'approval': approval_position = 0 for approval_role in doc_data['approval']["approval_roles"]: if g.user.roles_id.index(approval_role["role_id"]) >= 0 and "approved" not in approval_role: if "approval_users" in approval_role: for approval_users in approval_role["approval_users"]: if approval_users["user_id"] == g.user.id: raise CbsException(GENERIC_ERROR, u'Вы уже одобряли документ') approval_role["approval_users"].append({ "user_id": g.user.id, "approved": approve }) else: approval_role["approval_users"] = [] approval_role["approval_users"].append({ "user_id": g.user.id, "approved": approve }) if approve is True: if doc_data['approval']["approval_type"] == 'all': users_count = g.tran.query(db.User).filter_by(_deleted='infinity') \ .filter(db.User.roles_id.contains(type_coerce(approval_role["role_id"], JSONB))) if users_count == len(approval_role["approval_users"]): approval_role["approved"] = True try: if approval_position == len(doc_data['approval']["approval_roles"]) - 1: doc_data['document_status'] = 'approved' except IndexError: pass else: approval_role["approved"] = True try: if approval_position == len(doc_data['approval']["approval_roles"]) - 1: doc_data['document_status'] = 'approved' except IndexError: pass else: approval_role["approved"] = False doc_data['document_status'] = 'rejected' break approval_position += 1 pg_db = PostgresDatabase() if comment: pg_db.store({ "type": "DocumentComments", "document_id": doc_data['_id'], "data": { "comment_type": "approval" if approve is True else "rejection", "comment": comment } }) doc_data['type'] = 'Document' _id, _rev = pg_db.store(doc_data) return {"id": _id, "rev": _rev} elif bag['document_status'] == 'approved' and doc_data['document_status'] == 'approved': pg_db = PostgresDatabase() if comment: pg_db.store({ "type": "DocumentComments", "document_id": doc_data['_id'], "data": { "comment_type": "commit", "comment": comment } }) if doc_data['data']["executor_id"] == g.user.id and \ ('roles_id' not in doc_data['approval']): return self.commit(bag) elif doc_data['data']["executor_id"] == g.user.id: for role_id in doc_data['approval']['roles_id']: doc_data['approval']['approval_roles'].append({ "role_id": role_id }) bag['type'] = 'Document' bag['document_status'] = 'approval' bag['approval'] = doc_data['approval'] bag['data']['executor_id'] = doc_data['data']['executor_id'] bag['data']['user_id'] = doc_data['data']['user_id'] _id, _rev = pg_db.store(bag) return {"id": _id, "rev": _rev} raise CbsException(GENERIC_ERROR, u'Не подходящий статус документа')