Skip to content

Commit

Permalink
[pingan-custom] add ldap of external users and file-download log
Browse files Browse the repository at this point in the history
  • Loading branch information
r350178982 committed Nov 6, 2024
1 parent c2580c6 commit 92ea517
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 42 deletions.
11 changes: 10 additions & 1 deletion events/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from sqlalchemy.sql import exists

from .models import Event, UserEvent, FileAudit, FileUpdate, PermAudit, \
Activity, UserActivity, FileHistory
Activity, UserActivity, FileHistory, ExternalFileDownloadLog

from seafevents.app.config import appconfig

Expand Down Expand Up @@ -323,10 +323,19 @@ def save_file_audit_event(session, timestamp, etype, user, ip, device,

file_audit = FileAudit(timestamp, etype, user, ip, device, org_id,
repo_id, file_path)
session.add(file_audit)
session.commit()


def save_external_file_download_log(session, timestamp, user, ip, repo_id, file_path, size):
if timestamp is None:
timestamp = datetime.datetime.utcnow()

file_audit = ExternalFileDownloadLog(timestamp, user, ip, repo_id, file_path, size, datetime.datetime.now(), user, datetime.datetime.now(), user)
session.add(file_audit)
session.commit()


def save_perm_audit_event(session, timestamp, etype, from_user, to,
org_id, repo_id, file_path, perm):
if timestamp is None:
Expand Down
37 changes: 35 additions & 2 deletions events/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
from seafobj import CommitDiffer, commit_mgr, fs_mgr
from seafobj.commit_differ import DiffEntry
from seafevents.events.db import save_file_audit_event, save_file_update_event, \
save_perm_audit_event, save_user_activity, save_filehistory, update_user_activity_timestamp
save_perm_audit_event, save_user_activity, save_filehistory, update_user_activity_timestamp, \
save_external_file_download_log
from seafevents.app.config import appconfig
from .change_file_path import ChangeFilePathHandler
from .models import Activity

logger = logging.getLogger('seafevents')

def RepoUpdateEventHandler(session, msg):
elements = msg['content'].split('\t')
if len(elements) != 3:
Expand Down Expand Up @@ -425,7 +428,7 @@ def FileAuditEventHandler(session, msg):
if len(elements) != 6:
logging.warning("got bad message: %s", elements)
return

timestamp = datetime.datetime.utcfromtimestamp(msg['ctime'])
msg_type = elements[0]
user_name = elements[1]
Expand Down Expand Up @@ -498,6 +501,28 @@ def DraftPublishEventHandler(session, msg):
save_user_activity(session, record)


def ExternalFileAuditEventHandler(session, msg):
elements = msg['content'].split('\t')
if len(elements) != 6:
logging.warning("got bad message: %s", elements)
return

timestamp = datetime.datetime.utcfromtimestamp(msg['ctime'])
user_name = elements[1]
ip = elements[2]
repo_id = elements[4]
file_path = elements[5]

repo = seafile_api.get_repo(repo_id)
if repo.repo_type != 'external':
return
dirent = seafile_api.get_dirent_by_path(repo_id, file_path)
logging.warning(dirent.__dict__)
if not file_path.startswith('/'):
file_path = '/' + file_path
save_external_file_download_log(session, timestamp, user_name, ip, repo_id, file_path, dirent.size)


def register_handlers(handlers, enable_audit):
handlers.add_handler('seaf_server.event:repo-update', RepoUpdateEventHandler)
if enable_audit:
Expand All @@ -511,3 +536,11 @@ def register_handlers(handlers, enable_audit):
handlers.add_handler('seahub.audit:file-download-share-link', FileAuditEventHandler)
handlers.add_handler('seahub.audit:perm-change', PermAuditEventHandler)
handlers.add_handler('seahub.draft:publish', DraftPublishEventHandler)

#
handlers.add_handler('seahub.audit:file-download-web', ExternalFileAuditEventHandler)
handlers.add_handler('seahub.audit:file-download-api', ExternalFileAuditEventHandler)
handlers.add_handler('seahub.audit:file-download-share-link', ExternalFileAuditEventHandler)

# handlers.add_handler('seaf_server.event:repo-download-sync', ExternalFileAuditEventHandler)
# handlers.add_handler('seaf_server.event:seadrive-download-file', ExternalFileAuditEventHandler)
28 changes: 28 additions & 0 deletions events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,31 @@ def __str__(self):
RepoID = %s, FilePath = %s, Permission = %s>" % \
(self.etype, self.from_user, self.to,
self.repo_id, self.file_path, self.permission)


class ExternalFileDownloadLog(Base):
__tablename__ = 'ex_repo_download_log'

id = Column(Integer, primary_key=True, autoincrement=True)
timestamp = Column(DateTime, nullable=False, index=True)
user = Column(String(length=255), nullable=False, index=True)
ip = Column(String(length=45), nullable=False)
repo_id = Column(String(length=36), nullable=False, index=True)
file_path = Column(Text, nullable=False)
size = Column(BigInteger, nullable=False)
created_time = Column(DateTime, nullable=False)
created_by = Column(String(length=255), nullable=False)
updated_time = Column(DateTime, nullable=False)
updated_by = Column(String(length=255), nullable=False)

def __init__(self, timestamp, user, ip, repo_id, file_path, size, created_at, created_by, updated_at, updated_by):
self.timestamp = timestamp
self.user = user
self.ip = ip
self.repo_id = repo_id
self.file_path = file_path
self.size = size
self.created_time = created_at
self.updated_time = updated_at
self.created_by = created_by
self.updated_by = updated_by
3 changes: 3 additions & 0 deletions ldap_syncer/ldap_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def __init__(self):
self.duplicated_user_filter = None
# employee_type_attr: AD 中的一个自定义属性,标识账号类型
self.employee_type_attr = 'employeeType'
# external_user_filter: 用于过滤外部资料库权限的用户
self.external_user_filter = None

class Settings(object):
def __init__(self, is_test=False):
Expand Down Expand Up @@ -180,6 +182,7 @@ def read_base_config(self, ldap_config, ldap_sec, sync_sec, is_test, has_sync_se
ldap_config.group_filter = self.get_option(ldap_sec, 'GROUP_FILTER')

ldap_config.duplicated_user_filter = self.get_option(ldap_sec, 'DUPLICATED_USER_FILTER')
ldap_config.external_user_filter = self.get_option(ldap_sec, 'EXTERNAL_USER_FILTER')

if ldap_config.host == '' or ldap_config.user_dn == '' or ldap_config.passwd == '' or ldap_config.base_dn == '':
if is_test:
Expand Down
11 changes: 6 additions & 5 deletions ldap_syncer/ldap_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,25 @@ def start_sync(self):
data_ldap = self.get_data_from_ldap()
data_ldap_custom = self.get_data_from_ldap(use_duplicated_user_filter=True)
data_ladp_all = self.get_data_from_ldap(scope_all=True)
data_ldap_external = self.get_data_from_ldap(use_external_user_filter=True)
if data_ldap is None:
return

data_db = self.get_data_from_db()
if data_db is None:
return

self.sync_data(data_db, data_ldap, data_ladp_all)
self.sync_data(data_db, data_ldap, data_ladp_all, data_ldap_external)
self.cleanup_duplicated_ldap_data(data_ldap_custom)

def get_data_from_db(self):
return None

def get_data_from_ldap(self, use_duplicated_user_filter=False, scope_all=False):
def get_data_from_ldap(self, use_duplicated_user_filter=False, scope_all=False, use_external_user_filter=False):
ret = {}

for config in self.settings.ldap_configs:
cur_ret = self.get_data_from_ldap_by_server(config, use_duplicated_user_filter, scope_all)
cur_ret = self.get_data_from_ldap_by_server(config, use_duplicated_user_filter, scope_all, use_external_user_filter)
# If get data from one server failed, then the result is failed
if cur_ret is None:
return None
Expand All @@ -92,10 +93,10 @@ def get_data_from_ldap(self, use_duplicated_user_filter=False, scope_all=False):

return ret

def get_data_from_ldap_by_server(self, config, use_duplicated_user_filter=False, scope_all=False):
def get_data_from_ldap_by_server(self, config, use_duplicated_user_filter=False, scope_all=False, use_external_user_filter=False):
return None

def sync_data(self, data_db, data_ldap, data_ldap_all):
def sync_data(self, data_db, data_ldap, data_ldap_all, data_ldap_external):
pass

def cleanup_duplicated_ldap_data(self, data_ldap):
Expand Down
80 changes: 46 additions & 34 deletions ldap_syncer/ldap_user_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ def get_uid_to_ldap_user(self, data_ldap):

return uid_to_ldap_user

def get_data_from_ldap_by_server(self, config, use_duplicated_user_filter=False, scope_all=False):
def get_data_from_ldap_by_server(self, config, use_duplicated_user_filter=False, scope_all=False, use_external_user_filter=False):
if not config.enable_user_sync:
return {}
ldap_conn = LdapConn(config.host, config.user_dn, config.passwd, config.follow_referrals)
Expand All @@ -438,6 +438,16 @@ def get_data_from_ldap_by_server(self, config, use_duplicated_user_filter=False,
config.duplicated_user_filter)
else:
return None

# 使用 外部权限的用户 过滤
elif use_external_user_filter:

if config.external_user_filter:
search_filter = '(&(objectClass=%s)(%s))' % \
(config.user_object_class,
config.external_user_filter)
else:
return None

# search all users on base dn
elif config.user_filter != '':
Expand Down Expand Up @@ -584,8 +594,29 @@ def add_or_update_user_role_time(self, email, role):
logger.debug('Update role time to user %s successs.' % email)
except Exception as e:
logger.debug('Failed to update role time to user %s: %s.' % (email, e))

def sync_add_user(self, ldap_user, email, set_guest=False):

def set_external_user(self, email, set_external=False):
self.cursor.execute('select 1 from ex_repo_user where email=%s', [email])
if self.cursor.rowcount == 0:
if set_external:
sql = 'insert into ex_repo_user (email, created_time, created_by, updated_time, updated_by) values (%s,%s,%s,%s,%s)'
try:
self.cursor.execute(sql, [email, datetime.now(), 'ldap_sync', datetime.now(), 'ladp_sync'])
if self.cursor.rowcount == 1:
logger.debug('Create external user %s successs.' % email)
except Exception as e:
logger.debug('Failed to create external user %s: %s.' % (email, e))
else:
if not set_external:
sql = 'delete from ex_repo_user where email=%s'
try:
self.cursor.execute(sql, [email])
if self.cursor.rowcount == 1:
logger.debug('Create external user %s successs.' % email)
except Exception as e:
logger.debug('Failed to create external user %s: %s.' % (email, e))

def sync_add_user(self, ldap_user, email, set_guest=False, set_external=False):
user_id = add_ldap_user(email, ldap_user.password, 0,
1 if self.settings.activate_user else 0)
if user_id <= 0:
Expand Down Expand Up @@ -625,7 +656,9 @@ def sync_add_user(self, ldap_user, email, set_guest=False):
self.add_profile(email, ldap_user)
self.add_dept(email, ldap_user.dept)

def sync_update_user(self, ldap_user, db_user, email, new_email, set_guest=False):
self.set_external_user(email, set_external)

def sync_update_user(self, ldap_user, db_user, email, new_email, set_guest=False, set_external=False):
# PingAn customization: reactivate user when it's added back to AD.
if (email != new_email) or (db_user.password != ldap_user.password) or (db_user.is_active==0):
db_user.is_active = 1
Expand Down Expand Up @@ -684,6 +717,8 @@ def sync_update_user(self, ldap_user, db_user, email, new_email, set_guest=False
return
logger.debug('Reactivate user [%s] success.' % email)

self.set_external_user(email, set_external)

def sync_migrate_user(self, old_user, new_user):
if ccnet_api.update_emailuser_id(old_user, new_user) < 0:
logger.warning('Failed to update emailuser id to %s.' % new_user)
Expand Down Expand Up @@ -927,7 +962,7 @@ def sync_del_user(self, db_user, email):

# Note: customized for PinaAn's requirements. Do not deactivate renamed users in ldap.
# The checking of rename is based on profile_profile.login_id database field and uid attribute.
def sync_data(self, data_db, data_ldap, data_ldap_all):
def sync_data(self, data_db, data_ldap, data_ldap_all, data_ldap_external=None):
'''
:param data_db: seafile数据库中的用户数据
Expand All @@ -952,49 +987,26 @@ def sync_data(self, data_db, data_ldap, data_ldap_all):
logger.debug('User[%s] not found in ldap, '
'DEACTIVE_USER_IF_NOTFOUND option is not set, so not deactive it.' % del_user)

# collect migrated users
# nums = 0
# for k, v in data_ldap_all.items():
# if uid_to_users:
# uid = v.uid.lower()
# if uid in uid_to_users:
# found_active = False
# users = uid_to_users[uid]
# for user in users:
# if k == user:
# found_active = True
# break
#
# if found_active:
# for user in users:
# if k == user:
# continue
# nums = nums + 1
# continue
#
# for user in users:
# nums = nums + 1
#
# if nums > 0:
# logger.debug('%d users need migrate.' % nums)

# sync new and existing users from ldap to db
for k, v in data_ldap_all.items():
set_guest = False
set_external = False
if k not in data_ldap.keys(): # 如果用户不在设置的安全组里
set_guest = True
if k in data_ldap_external.keys():
set_external = True
if uid_to_users:
uid = v.uid.lower()
if uid not in uid_to_users:
if self.settings.import_new_user:
self.sync_add_user(v, k, set_guest=set_guest)
self.sync_add_user(v, k, set_guest=set_guest, set_external=set_external)
else:
found_active = False
users = uid_to_users[uid]
for user in users:
if k == user:
if user in data_db:
self.sync_update_user(v, data_db[user], user, k, set_guest=set_guest)
self.sync_update_user(v, data_db[user], user, k, set_guest=set_guest, set_external=set_external)
found_active = True
break

Expand All @@ -1009,7 +1021,7 @@ def sync_data(self, data_db, data_ldap, data_ldap_all):
continue

email = users[0]
self.sync_update_user(v, data_db[email], email, k, set_guest=set_guest)
self.sync_update_user(v, data_db[email], email, k, set_guest=set_guest, set_external=set_external)
for user in users:
self.sync_migrate_user(user, k)
if email != user:
Expand Down

0 comments on commit 92ea517

Please sign in to comment.