From 0b9cd46506f7ff63ec49963570fac1becf313c4b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 14 May 2015 20:56:48 +0200 Subject: [PATCH] added simple python script to manage owncloud shares --- python/sciebo_shares.py | 189 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 python/sciebo_shares.py diff --git a/python/sciebo_shares.py b/python/sciebo_shares.py new file mode 100644 index 0000000..5637edd --- /dev/null +++ b/python/sciebo_shares.py @@ -0,0 +1,189 @@ +import owncloud +import requests +import re +import sys +import posixpath +import urlparse + +import xml.etree.ElementTree as ET + +from tidylib import tidy_document + +PATH = 'Master.ET-IT-TI/' +USER = '' +PASS = '' +OWNCLOUD = 'https://rwth-aachen.sciebo.de' + +TITLES = ['Wirt.-Ing.', 'Priv.-Doz.', 'E.h.', 'Ph. D.', 'Univ.', 'habil.', 'Dipl.', 'Prof.', 'Dr', 'Ing', 'rer.', 'dent.', 'paed.', 'nat.', 'phil.', 'Inform.', 'apl', 'Kff.', 'Kfm.', 'med.', 'B. Sc.', 'M. Sc.', 'B. A.', 'M. A.', 'RWTH', 'Chem', ',', '.', '-', '/', '\\'] +WHITELIST = ['Z608AD@rwth-aachen.de', '121EHT@rwth-aachen.de', '6ANU61@rwth-aachen.de', 'FTD971@rwth-aachen.de', 'NB92H4@rwth-aachen.de'] + +def strip_ns(xml_string): + return re.sub('xmlns="[^"]+"', '', xml_string) + +def simplify_name(name): + for token in TITLES: + name = name.replace(token, " ") + + name = re.sub("\s\s+", " ", name) + name = re.sub("^\s+", "", name) + name = re.sub("\s+$", "", name) + + return name + +# At least one lastname and one firstname have to match +def check_employee(lastname, firstname): + firstname = simplify_name(firstname) + lastname = simplify_name(lastname) + + employees = get_employees(lastname, firstname) + critical = [ ] + + firstnames = set(firstname.lower().split(" ")) + lastnames = set(lastname.lower().split(" ")) + + for employee in employees: + employee2 = set(simplify_name(employee).lower().split(" ")) + isect1 = employee2.intersection(firstnames) + isect2 = employee2.intersection(lastnames) + if len(isect1) and len(isect2): + critical.append(employee) + + return critical + +def get_employees(lastname, firstname): + payload = { 'find' : lastname } + res = requests.get('https://www.campus.rwth-aachen.de/rwth/all/lecturerlist.asp', params=payload) + if res.status_code == 200: + persons = [ ] + + document, errors = tidy_document(res.content, options={'numeric-entities': 1, 'output_xhtml': 1}) + tree = ET.fromstring(strip_ns(document)) + + filename = posixpath.basename(urlparse.urlsplit(res.url).path) + if filename == 'lecturer.asp': + fullname = tree.find('body/table[1]/tr[3]//tr[2]/td[2]').text.strip() + unit = tree.find("body/table[2]//td[@class='h3']/a").text.strip() + + persons.append(fullname) + + elif filename == 'lecturerlist.asp': + links = [ ] + for cell in tree.findall('body/table[2]//td[3]/table[2]//td[1]/a'): + if cell is not None: + fullname = cell.text.strip() + persons.append(fullname) + else: + raise Exception('Failed to get employee info') + + return persons + +def get_share(self, id): + data = 'shares/%u' % id + + res = self._Client__make_ocs_request( + 'GET', + self.OCS_SERVICE_SHARE, + data + ) + if res.status_code == 200: + tree = ET.fromstring(res.content) + self._Client__check_ocs_status(tree) + element = tree.find('data').find('element') + share_attr = {} + for child in element: + key = child.tag + value = child.text + share_attr[key] = value + return share_attr + raise ResponseError(res) + + +def add_shares(oc, shares): + # Get list of existing shares + existing = [ ] + for share in shares: + existing.append(share['share_with']) + + for line in sys.stdin: + id = line.strip() + + match = re.match('[A-Z0-9]{6}@rwth-aachen.de', id) + if match: + if id in existing: + share = (item for item in shares if item['share_with'] == id).next() + print '%s already is in share list' % share['share_with_displayname'] + continue + + try: + share = oc.share_file_with_user(PATH, id, perms=oc.OCS_PERMISSION_READ|oc.OCS_PERMISSION_CREATE) + details = get_share(oc, share.share_id) + + match = re.match('([^,]*), ([^(]*) \(', details['share_with_displayname']) + if match: + lastname = match.group(1) + firstname = match.group(2) + critical = check_employee(lastname, firstname) + if len(critical): + print "===> ATTANTION: %s maybe an employee!! Add manually!!!" % details['share_with_displayname'] + print " We found these employees with similar names in Campus Office:" + for employee in critical: + print ' %s' % employee + continue + + print 'Added %s' % details['share_with_displayname'] + + except owncloud.ResponseError as e: + print 'Failed to add: %s' % e.response.content.strip() + +def check_shares(oc, shares): + for share in shares: + if share['share_with'] in WHITELIST: + continue + + match = re.match('([^,]*), ([^(]*) \(', share['share_with_displayname']) + if match: + lastname = match.group(1) + firstname = match.group(2) + critical = check_employee(lastname, firstname) + + if len(critical): + print "===> ATTENTION: %s maybe an employee!!!" % share['share_with_displayname'] + print " We found these employees with similar names in Campus Office:" + for employee in critical: + print ' %s' % employee + else: + raise Exception("Failed to match share_id") + +def list_shares(oc, shares, admin=False): + print "Perm, Name, Added By" + + for share in shares: + if not admin or share['permissions'] != '5': + if 'displayname_owner' not in share.keys(): + share['displayname_owner'] = '!!unknown!!' + + print "%s%s%s" % (share['permissions'].ljust(3), share['share_with_displayname'].ljust(65).encode('utf-8'), share['displayname_owner']) + + print '=== Total: %u' % len(shares) + +if __name__ == "__main__": + print "### Owncloud / Sciebo share manager" + + oc = owncloud.Client(OWNCLOUD) + oc.login(USER, PASS) + + # Get list of already existing IDs + shares = oc.get_shares(PATH, reshares=True) + + if len(sys.argv) >= 2: + command = sys.argv[1] + else: + command = 'add' + + if command == 'add': + add_shares(oc, shares) + elif command == 'list': + admin = (len(sys.argv) == 3) and (sys.argv[2] == 'admin') + list_shares(oc, shares, admin) + elif command == 'check': + check_shares(oc, shares) \ No newline at end of file