Flask構(gòu)建SaaS應(yīng)用

租戶(hù)隔離

一個(gè)客戶(hù)就是一個(gè)租戶(hù)曲梗,每個(gè)租戶(hù)的數(shù)據(jù)在數(shù)據(jù)表中都有個(gè)一個(gè)tenantid字段用來(lái)與其他租戶(hù)隔離

  • 租戶(hù)識(shí)別
from flask import g, request
    
def get_tenant_from_request():
    auth = validate_auth(request.headers.get('Authorization'))
    return Tenant.query.get(auth.tenant_id)
        
def get_current_tenant():
    rv = getattr(g, 'current_tenant', None)
    if rv is = None:
        rv = get_tenant_from_request()
        g.current_tenant = rv
    return rv
  • 自動(dòng)租戶(hù)隔離

例如纤垂,每個(gè)租戶(hù)有自己的Project逸吵,像下面這樣批量直接修改project又忘記帶上tenantid查詢(xún)字段损肛,就會(huì)把其他租戶(hù)的project一并修改了

def batch_update_projects(ids, changes):
    projects = Project.query.filter(
        Project.id.in_(ids) &
        Project.status != ProjectStatus.INVISIBLE
    )
    for project in projects: 
        update_projects(project, changes)

我們可以override Project的query屬性以及使用sqlalchemy的event listener來(lái)自動(dòng)的進(jìn)行租戶(hù)隔離厢破,也就是說(shuō)我們?cè)谑褂胦rm查詢(xún)的時(shí)候,會(huì)自動(dòng)帶上tenentid查詢(xún)字段治拿,這樣無(wú)論是修改摩泪、刪除、查詢(xún)都只會(huì)是操作自己租戶(hù)下面的數(shù)據(jù)劫谅,畢竟在orm中见坑,刪除和修改都是要先查詢(xún)的嘛

# model
class Project(TenantBoundMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    status = db.Column(db.Integer)
    def __repr__(self):
        return '<Project name=%r>' % self.name
from sqlalchemy.ext.declarative import declared_attr
?
# 覆寫(xiě)Project類(lèi)的query_class屬性
class TenantQuery(db.Query):
    current_tenant_constrained = True
    def tenant_unconstrained_unsafe(self):
        rv = self._clone()
        rv.current_tenant_constrained = False
        return rv
# 通過(guò)mixin的方式嚷掠,讓Project類(lèi)多繼承這個(gè)類(lèi)
# 從而覆寫(xiě)了Project類(lèi)的query_class屬性
class TenantBoundMixin(object):
    query_class = TenantQuery
    # 為project表定義了一個(gè)tenant_id字段
    @declared_attr
    def tenant_id(cls):
        return db.Column(db.Integer, db.ForeignKey('tenant.id'))
?
    @declared_attr
    def tenant(cls):
        return db.relationship(Tenant, uselist=False)
?
# event_listener的意思是,每次執(zhí)行例如Project.query的時(shí)候都會(huì)執(zhí)行
# 下面的鉤子函數(shù)荞驴,
# 這個(gè)鉤子函數(shù)會(huì)給query對(duì)象帶上ilter_by(tenant=get_current_tenant())
@db.event.listens_for(TenantQuery, 'before_compile', retval=True)
def ensure_tenant_constrained(query):
    for desc in query.column_descriptions:
        if hasattr(desc['type'], 'tenant') and \
            query.current_tenant_constrained:
              query = query.filter_by(tenant=get_current_tenant())
    return query

接下來(lái)我們來(lái)看一下使用

# 只查詢(xún)我這個(gè)租戶(hù)名下的project42
>>> Project.query.all()
[<Project name='project42'>]
# 去掉租戶(hù)約束不皆,查詢(xún)所有project信息
>>> Project.query.tenant_unconstrained_unsafe().all()
[<Project name='project1'>, Project.name='project2', ...]

審計(jì)日志

def log(action, message=None):
  data = {
        'action': action
        'timestamp': datetime.utcnow()
  }
  if message is not None:
         data['message'] = message
  if request:
         data['ip'] = request.remote_addr
  user = get_current_user()
  if user is not None:
         data['user'] = User
  db.session.add(LogMessage(**data))

更多詳細(xì)信息,請(qǐng)參考

flask多租戶(hù)實(shí)踐
完整版
https://johnson329.github.io/flask/flask%E6%9E%84%E5%BB%BAsaas%E5%BA%94%E7%94%A8/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熊楼,一起剝皮案震驚了整個(gè)濱河市霹娄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鲫骗,老刑警劉巖犬耻,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異执泰,居然都是意外死亡香追,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)坦胶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人晴楔,你說(shuō)我怎么就攤上這事顿苇。” “怎么了税弃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵纪岁,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我则果,道長(zhǎng)幔翰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任西壮,我火速辦了婚禮遗增,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘款青。我一直安慰自己做修,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布抡草。 她就那樣靜靜地躺著饰及,像睡著了一般。 火紅的嫁衣襯著肌膚如雪康震。 梳的紋絲不亂的頭發(fā)上燎含,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音腿短,去河邊找鬼屏箍。 笑死绘梦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铣除。 我是一名探鬼主播谚咬,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼尚粘!你這毒婦竟也來(lái)了择卦?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤郎嫁,失蹤者是張志新(化名)和其女友劉穎秉继,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體泽铛,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尚辑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盔腔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杠茬。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖弛随,靈堂內(nèi)的尸體忽然破棺而出瓢喉,到底是詐尸還是另有隱情,我是刑警寧澤舀透,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布栓票,位于F島的核電站,受9級(jí)特大地震影響愕够,放射性物質(zhì)發(fā)生泄漏走贪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一惑芭、第九天 我趴在偏房一處隱蔽的房頂上張望坠狡。 院中可真熱鬧,春花似錦遂跟、人聲如沸擦秽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)感挥。三九已至,卻和暖如春越败,著一層夾襖步出監(jiān)牢的瞬間触幼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工究飞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留置谦,地道東北人堂鲤。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像媒峡,于是被迫代替她去往敵國(guó)和親瘟栖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 租戶(hù)隔離 一個(gè)客戶(hù)就是一個(gè)租戶(hù)谅阿,每個(gè)租戶(hù)的數(shù)據(jù)在數(shù)據(jù)表中都有個(gè)一個(gè)tenantid字段用來(lái)與其他租戶(hù)隔離 租戶(hù)識(shí)別...
    看五年前自己的文章真是唏噓不已閱讀 675評(píng)論 0 1
  • ABP總體介紹 ABP是ASP.NET Boilerplate Project半哟,ASP.NET樣板項(xiàng)目。 ABP框...
    JunChow520閱讀 19,072評(píng)論 0 9
  • 這幾年签餐,在公司嘗試轉(zhuǎn)型做產(chǎn)品寓涨。所以引入了很多的產(chǎn)品的理念。不管是對(duì)產(chǎn)品的定義氯檐,還是針對(duì)產(chǎn)品的管理戒良,以及摸索產(chǎn)品的落...
    NeilZhou閱讀 32,173評(píng)論 0 33
  • 久違的晴天,家長(zhǎng)會(huì)冠摄。 家長(zhǎng)大會(huì)開(kāi)好到教室時(shí)糯崎,離放學(xué)已經(jīng)沒(méi)多少時(shí)間了。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)河泳。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,515評(píng)論 16 22
  • 今天感恩節(jié)哎拇颅,感謝一直在我身邊的親朋好友。感恩相遇乔询!感恩不離不棄。 中午開(kāi)了第一次的黨會(huì)韵洋,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,559評(píng)論 0 11