# -*- coding: utf-8 # $Id$ # # # Copyright 2001, 2002 by IVA Team and contributors # # This file is part of IVA. # # IVA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # IVA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with IVA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Contains class UserInfo, which contains the FLE specific details of registered users.""" __version__ = "$Revision$"[11:-2] import time, datetime, string, types, datetime import os.path try: from PIL import Image PIL_imported = 1 except ImportError: PIL_imported = 0 import cStringIO import Globals import OFS from Globals import Persistent, Acquisition import AccessControl from AccessControl import ClassSecurityInfo, getSecurityManager from zope.interface import implements from interfaces import IStatistics, ICourseManager, IFLE, IUserInfo import TraversableWrapper from Cruft import Cruft from Webtop import Webtop from CourseManager import IDManager from common import get_url, styles_path, \ make_action, get_roles, get_local_roles, translate #from common import user_timeout_delay #from TempObjectManager import TempObjectManager from input_checks import render, is_valid_title, is_valid_url, normal_entry_tags from common import perm_view, perm_edit, perm_manage, perm_add_lo from Globals import PersistentMapping import re try: from Products.ZWiki.ZWikiPage import ZWikiPage USE_ZWIKI = 1 except: USE_ZWIKI = 0 import Kirjakast import Kalender import Blog from Products.ZCatalog.CatalogPathAwareness import CatalogAware from Errors import FleError from zope.component import getUtility bg_stuff = { 'bgcolor_rd': ('rd', 'cc3333'), 'wt_bg_bl': ('bl','3f82b5'), 'wt_bg_gray1': ('gray', 'c0c0c0'), 'wt_bg_gray2': ('gray', '99af73'), 'wt_bg_tq': ('tq', '93bdb6'), 'wt_bg_yl': ('yl', 'c2c32e'), } # An instance of this class holds all user specific information # with the exception of access control, which is handled by the # standard Zope objects in acl_users. IVA no longer has global # roles, but rather local roles attached to the FLE root object. # # Some acl information is handled here (like password changing), # but those functions transfer to Zope internals as fast as possible. class UserInfo( OFS.Folder.Folder, Persistent, TraversableWrapper.TraversableWrapper, Cruft, AccessControl.Role.RoleManager, OFS.SimpleItem.Item, IDManager, CatalogAware, ): """FLE user information.""" meta_type = 'UserInfo' security = ClassSecurityInfo() security.declareObjectPublic() implements(IUserInfo) def __init__(self, id_, uniq_id=''): """Construct UserInfo object.""" security = ClassSecurityInfo() self.id = id_ #self.title = title self.title = '' self.uname = id_ self.id=id_ self.jooksev_kursus=0; self.__last_active = {} self.__frozen = 0 self.email_hinded=0 self.email_kirjad=0 self.email_raamat=0 self.email_teadm=0 self.email_meedia=0 self.eventLimit = 1 # in weeks! 1 = one week self.setUniqId(uniq_id) self.__edit_tbl = PersistentMapping() IDManager.__init__(self) self.default_catalog = 'userinfo_zcatalog' # Set permissions: # We iterate first over all set_* methods in this class, and protect them # with the Edit permission (see manage_afterAdd), and then we set the # View permissions for all get_* methods. for prefix in ['set_', 'get_']: for func in filter(lambda x,p=prefix:x[:len(p)] == p, dir(self)): if prefix == 'set_': security.declareProtected('Edit', func) elif prefix == 'get_': security.declareProtected('View', func) #self.set_first_name(first_name) #self.set_last_name(last_name) #self.set_email(email) #self.set_language(language) ## NOTE: Wrong. Stuff like this should have their own container classes. #self.set_photo(photo) # This is picture binary data self.set_group('') self.set_address1('') self.set_address2('') self.set_city('') self.set_country('Estonia') self.set_homepage('') self.set_phone('') self.set_gsm('') self.set_quote('') self.set_background('') self.set_personal_interests('') self.set_professional_interests('') self.set_language('et') # Dirty hack .. self.longLinks = [] self.longLinkQueue = [] self.eventLimit = 1 # in weeks! 1 = one week # try: # self.set_language(self.get_default_language()) # except: # pass self.set_organization('') security.declarePrivate('manage_afterAdd') def manage_afterAdd(self, item, container): """Set default permissions for roles.""" # wt = Webtop().__of__(self) wt=Webtop() wt.id='webtop' self._setObject('webtop', wt) # add blog blog = Blog.Blog() self._setObject(blog.id, blog) # add mailbox self._setObject('kirjad', Kirjakast.Kirjakast()) # add events container em = Kalender.KalendriSyndmusteKataloog() self._setObject(em.id, em) sm = getattr(self, em.id) self.set_language(self.get_default_language()) for obj in (self, self.get_child('webtop')): obj.manage_delLocalRoles([t[0] for t in obj.get_local_roles()]) obj.manage_setLocalRoles(self.get_uname(), ('Owner',)) from common import roles_admin, roles_staff, roles_user self.index_object() security.declareProtected(perm_view, 'get_photo_tag') # Our (simple) version of the tag() method of Zope's Image class. def get_photo_tag(self, **args): """Return HTML img tag for user's photo.""" fle_root = self.fle_root() fle_url = fle_root.absolute_url() fle_url = self.fle_url() tag = "" imgp = getattr(self.fle_root().images, 'users_imgs') img = getattr(imgp, 'user_'+self.get_uname()+'_image', None) if img is not None: # user has image if args.has_key('width') and not args.has_key('height'): mod = float(args['width'])/float(img.width) args['height'] = int(img.height*mod) elif args.has_key('height') and not args.has_key('width'): mod = float(args['height'])/float(img.height) args['width'] = int(img.width*mod) tag = apply(img.tag, [], args) else: # user don't have image args['width']='32' args['height']='32' uimg = self.unrestrictedTraverse('++resource++images/user.gif') #imgs_path = getattr(self.fle_root(), self.getSkinsFolderName()).images #tag = apply(getattr(imgs_path, 'user.gif').tag, [], args) tag = '' tag = tag.replace(fle_url+'/', '') return tag def get_photo_url(self): """ url where photo is """ imgp = getattr(self.fle_root().images, 'users_imgs') img = getattr(imgp, 'user_'+self.get_uname()+'_image', None) if img is not None: return img.absolute_url() return "" def get_photo_obj(self): """ return photo object """ imgp = getattr(self.fle_root().images, 'users_imgs') img = getattr(imgp, 'user_'+self.get_uname()+'_image', None) return img security.declareProtected(perm_view, 'has_photo') def has_photo(self): """Return whether user has photo.""" path = getattr(self.fle_root().images, 'users_imgs') img = getattr(path, 'user_'+self.get_uname()+'_image', 0) if not img: return 0 else: return 1 security.declareProtected(perm_view, 'get_webtop') def get_webtop(self): """Return the webtop of the user.""" return self.get_child('webtop') def getPassword(self): return self.acl_users.getUser(self.get_uname())._getPassword() # Get "global" roles, eg. the roles given for the FLE root object. def getRoles(self): return get_roles(self.parent().parent(),self.get_uname()) # def getFrozenRoles(self): # return self.__roles # Get roles specified for just one object, and not acquired from above. def getRolesInObject(self,object): return get_local_roles(object,self.get_uname()) security.declareProtected(perm_view, 'user_courses') def user_courses(self, REQUEST=None, update=None,filter_dead=0, quick=0): """Return a list of the courses the user is on. Sorted by last activity""" # Two ways to get user's course. # * from groups. # with around 1000 groups in acl_users, this took around ~0.001 sec # * using zcatalog # two courses indexed, this took around 0.001 and sometimes less. # resolution: for now, it seems using zcatalog is faster... using stuff like ldapuserfolder is definitly slowing # acl_users down. Using ZCatalog is rarely slower. #st = time.time() #print self.acl_users._getGroupsForPrincipal(self.acl_users.getUser(self.get_uname())) #print "end 1:", time.time()-st #st = time.time() cm = getUtility(ICourseManager) uname = self.get_uname() q = {'meta_type': 'Course', 'get_all_users_id':uname} cl = cm.courses_zcatalog(q) if quick: return cl # getUserCourseStat stat='lastAccess' cids = [ x.get_id for x in cl ] cids = str(tuple(cids)) if cids[-2] == ',': cids[:-2] + ")" sqlres = getUtility(IStatistics).getUserCourseStatMultiple(cids, 'lastAccess', uname) if sqlres is None: return cl tmp = {} for c in cl: tmp[c.get_id] = [0, c] for r in sqlres: tmp[r.course_id][0] = time.mktime(r.lastAccess.utctimetuple()) def _cmp(o1, o2): if o1[0] < o2[0]: return -1 if o1[0] > o2[0]: return 1 return 0 tmp = tmp.values() tmp.sort(_cmp) tmp.reverse() # TODO: # isCourseAlive # filter_dead #print "end 2:", time.time()-st #return cl return [ x[1] for x in tmp ] security.declareProtected(perm_view,'set_jooksev_kursus') def set_jooksev_kursus(self, kursus, user): """ change course """ fle = getUtility(IFLE) cm = getUtility(ICourseManager) if not hasattr(cm, kursus): self.jooksev_kursus = 0 return 0 x = getattr(cm, kursus) user = getSecurityManager().getUser() if user.has_role(('IVAAdmin','Manager',)): #was user.has_role self.jooksev_kursus=kursus return 1 islock = x.isLocked() if islock: return 0 ac_user = fle.acl_users.getUser(self.get_uname()) for x in fle.acl_users._getGroupsForPrincipal(ac_user): if x == kursus or x == kursus+'_teachers' : self.jooksev_kursus = kursus return 1 return 0 security.declarePublic('get_jooksev_kursus') def get_jooksev_kursus(self): """ current course """ jk = getattr(self, 'jooksev_kursus', 0) x = getattr(getUtility(ICourseManager), str(jk), None) if x is None: return 0 islock = x.isLocked() if islock and not self.has_any_role(('IVAAdmin','Manager',)): self.jooksev_kursus = 0 return jk def kysiJooksvaKursuseObjekt(self): "Kursus kasutatava objektina" try: return getattr(self.fle_root().courses, self.get_jooksev_kursus()) except: return "viga" def kysiJooksvaKursuseSisegrupid(self): "Sisegruppide loetelu" k=self.kysiJooksvaKursuseObjekt() return self.kysiKursuseSisegrupid(k) def kysiKursuseSisegrupid(self, kursus): "Kursusel olevad grupid" if not hasattr(kursus, 'subgroups'): return [] m=kursus.subgroups.getSubgroups() loetelu=[] for x in m: #XXX: check me r=x.get_local_roles() for paar in r: #if paar[0]==self.get_uname() and ('User' in paar[1] or 'Owner' in paar[1]): loetelu.append(x) return loetelu security.declarePrivate('check_portfolios') def check_portfolios(self, obj, course_obj): """ Creates portfolio for user obj - must be user's course folder eg. /fle_users/vahur/webtop/c12 course_obj - course object """ portfolio = getattr(obj.aq_inner, 'portfolio', None) if not portfolio: obj.add_portfolio() obj.portfolio.setObjPermission(4) assignments = course_obj.kodutood.listAssignments() todo = [] for x in assignments: if x.tyyp in [0,1,4,5]: todo.append(x) if todo: for x in todo: m_id = x.get_id() asg = getattr(obj.portfolio.aq_self, m_id, None) if not asg: obj.portfolio.createAssignmentProxy(m_id, course_obj.get_id()) if x.tyyp==5: kaust=getattr(obj.portfolio, m_id) try: map=getattr(course_obj.wordmaps, x.getWmID()) mapcopy=map.addChildMap(copying=1) mapcopy.visibletoothers=0 #kaust.add_link("link to map", mapcopy.absolute_url(), 1) kaust.wmcID=map.absolute_url()+"/"+mapcopy.id mapcopy.homeworkstatus=1; mapcopy.hwid=x.id except: pass def kasKeelBrauserist(self): """ if 1 we should use language that is preferred by browser """ return getattr(self, 'keelBrauserist', 0) def seaKeelBrauserist(self, seisund): """Soovitu seadmine""" if seisund: self.keelBrauserist = 1 else: self.keelBrauserist = 0 security.declareProtected(perm_edit, 'set_language') def set_language(self, lang): """Set language.""" if lang in get_languages(): self.language = lang security.declareProtected(perm_view, 'get_language') def get_language(self): """Get language.""" if self.language is None: raise 'FLE Error', 'No language set.' return self.language security.declareProtected(perm_edit, 'set_first_name') def set_first_name(self, name): """Set first name.""" self.__first_name = name security.declareProtected(perm_edit, 'set_last_name') def set_last_name(self, name): """Set last name.""" self.__last_name = name security.declareProtected(perm_edit, 'set_email') def set_email(self, email): """Set email.""" self.__email = email security.declareProtected(perm_edit, 'set_language') def set_language(self, language): """Set language.""" self.__language = language security.declareProtected(perm_edit, 'remove_photo') def remove_photo(self): """ removes photo """ imgp = getattr(self.fle_root().images, 'users_imgs') try: imgp._delObject('user_'+str(self.get_id())+'_image') except AttributeError: pass security.declareProtected(perm_edit, 'set_photo') def set_photo(self, photo, content_type=None): """Set photo.""" imgp = getattr(self.fle_root().images, 'users_imgs') try: imgp._delObject('user_'+str(self.get_id())+'_image') except AttributeError: pass try: # Try to crop and scale image to 32x32 pixels and # convert it into JPEG format... if not PIL_imported: print "Can't scale user's photo. PIL not installed." raise '' s = cStringIO.StringIO(photo) im = Image.open(s) (width, height) = im.size #if width == 32 and height == 32 and im.format == 'JPEG': if height == 80 and im.format == 'JPEG': # If the image is already 32x32 JPEG image, we want to # avoid doing JPEG compression again (lossy!) # This is important when exporting/importing FLE. pass if im.mode != 'RGB': im = im.convert('RGB') if width != height: smaller = min(width, height) bigger = max(width, height) # if width == smaller: # Tall image: save top part of the image # im = im.crop(( 0, 0, smaller, smaller)) # else: # Wide image: save center part of the image # im = im.crop(( (width-height)/2, 0, smaller, smaller)) #im = im.resize((32,32), Image.BICUBIC) if height > 80: #u_w = float(width)/float(height) mod = float(80)/float(height) width = width*mod height = height*mod im = im.resize((int(width),int(height))) if width > 100: u_w = float(100)/float(width) width = width*u_w height = height*u_w im = im.resize((int(width),int(height))) s = cStringIO.StringIO() try: im.save(s, "JPEG", quality=100) except KeyError: im.save(s, "GIF", quality=100) s.seek(0) imgp.manage_addImage('user_'+str(self.get_uname())+'_image', s.read(), 'user\'s image') img = getattr(imgp, 'user_'+str(self.get_uname())+'_image') img.ZCacheable_setManagerId('HTTPCache') img.ZCacheable_invalidate() #self.__photo = s.read() except: # ... or failing that just use the original image. # (The failure happens if the system has not PIL installed, # or if the PIL can't read the image format, or if the PIL # was compiled without JPEG support, or then something # completely different...) #imgp.manage_addImage('user_'+str(self.get_uname())+'_image', photo, 'user\'s image') #img = getattr(imgp, 'user_'+str(self.get_uname())+'_image') #img.ZCacheable_setManagerId('HTTPCache') #img.ZCacheable_invalidate() return 1 #self.__photo = photo # FIXME: user can change his own group! # We can do this by calling this method from another # method that does custom access checking. security.declareProtected(perm_edit, 'set_group') def set_group(self, group): """Set group.""" self.__group = group security.declareProtected(perm_edit, 'set_address1') def set_address1(self, address1): """Set address.1 (street address)""" self.__address1 = address1 security.declareProtected(perm_edit, 'set_address2') def set_address2(self, address2): """Set address.2 (postal address)""" self.__address2 = address2 security.declareProtected(perm_edit, 'set_city') def set_city(self, city): """Set city.""" self.__city = city security.declareProtected(perm_edit, 'set_country') def set_country(self, country): """Set country.""" self.__country = country security.declareProtected(perm_edit, 'set_homepage') def set_homepage(self, homepage): """Set homepage.""" self.__homepage = homepage security.declareProtected(perm_edit, 'set_phone') def set_phone(self, phone): """Set phone.""" self.__phone = phone security.declareProtected(perm_edit, 'set_gsm') def set_gsm(self, gsm): """Set gsm.""" self.__gsm = gsm security.declareProtected(perm_edit, 'set_quote') def set_quote(self, quote): """Set quote.""" self.__quote = quote security.declareProtected(perm_edit, 'set_background') def set_background(self, background): """Set background.""" self.__background = background security.declareProtected(perm_edit, 'set_personal_interests') def set_personal_interests(self, p_i): """Set personal interests.""" self.__personal_interests = p_i security.declareProtected(perm_edit, 'set_professional_interests') def set_professional_interests(self, p_i): """Set professional interests.""" self.__professional_interests = p_i security.declareProtected(perm_edit, 'set_organization') def set_organization(self, p_i): """Set organization.""" self.__organization = p_i security.declarePublic('get_uname') def get_uname(self): """Get user name.""" return self.uname security.declarePublic('get_nickname') def get_nickname(self): """Get user's visible nick name.""" try: return self.nickname except AttributeError: return self.uname security.declarePrivate('fingerNames') def fingerNames(self): """ Fetch names via finger """ HOST = self.getFingerHost() PORT = self.getFingerPort() import socket, re, string sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(2.0) try: sock.connect((HOST,PORT)) except FleError: return 0 sock.send('-m %s\n' % string.lower(self.get_uname())) response = sock.recv(1024) sock.close() if len(response)<30+len(self.get_uname()): return 0 name = re.search('Name:.*?\r',response).group().strip().split(' ') name.remove('Name:') logname = re.search('Login:.*?\t',response).group().strip().split(' ') logname.remove('Login:') if logname[0] and logname[0]== string.lower(self.get_uname()): if len(name)==2: #we have two (first and last) names try: firstname = name[0].decode('utf-8') except UnicodeDecodeError: firstname = name[0].decode('iso-8859-15') try: lastname = name[1].decode('utf-8') except UnicodeDecodeError: lastname = name[1].decode('iso-8859-15') firstname = firstname.encode('utf-8') lastname = lastname.encode('utf-8') self.set_first_name(firstname) self.set_last_name(lastname) elif len(name)<2: # somethings missing return 0 elif len(name)>2: # more than 2 names try: firstname = name[0].decode('utf-8') except UnicodeDecodeError: firstname = name[0].decode('iso-8859-15') firstname = firstname.encode('utf-8') self.set_first_name(firstname) name.remove(name[0]) lname = "" for x in name: if lname: lname += ' ' lname += x try: lastname = lname.decode('utf-8') except UnicodeDecodeError: lastname = lname.decode('iso-8859-15') lastname = lastname.encode('utf-8') self.set_last_name(lastname) self.reindex_object() return 1 security.declareProtected(perm_view,'get_first_name') def get_first_name(self): """Get first name.""" if not hasattr(self, '_' + self.__class__.__name__+ '__first_name'): return "" else: return self.__first_name security.declareProtected(perm_view,'get_last_name') def get_last_name(self): """Get last name.""" if not hasattr(self, '_' + self.__class__.__name__+ '__last_name'): return "" else: return self.__last_name security.declareProtected(perm_view, 'get_email') def get_email(self): """Get email.""" if not hasattr(self, '_' + self.__class__.__name__+ '__email'): return "" else: return self.__email security.declareProtected(perm_view, 'get_language') def get_language(self): """Get language.""" if not hasattr(self, '_' + self.__class__.__name__+ '__language'): return "" else: return self.__language security.declareProtected(perm_view, 'get_group') def get_group(self): """Get group.""" # FIXME: This can't be defined here. if not hasattr(self, '_' + self.__class__.__name__+ '__group'): return "" else: return self.__group security.declareProtected(perm_view, 'get_address1') def get_address1(self): """Get address1. (street address)""" if not hasattr(self, '_' + self.__class__.__name__+ '__address1'): return "" else: return self.__address1 security.declareProtected(perm_view, 'get_address2') def get_address2(self): """Get address2. (postal address2)""" if not hasattr(self, '_' + self.__class__.__name__+ '__address2'): return "" else: return self.__address2 security.declareProtected(perm_view, 'get_country') def get_country(self): """Get country.""" if not hasattr(self, '_' + self.__class__.__name__+ '__country'): return "" else: return self.__country security.declareProtected(perm_view, 'get_homepage') def get_homepage(self): """Get homepage.""" if not hasattr(self, '_' + self.__class__.__name__+ '__homepage'): return "" else: return self.__homepage security.declareProtected(perm_view, 'get_phone') def get_phone(self): """Get phone.""" if not hasattr(self, '_' + self.__class__.__name__+ '__phone'): return "" else: return self.__phone security.declareProtected(perm_view, 'get_gsm') def get_gsm(self): """Get gsm.""" if not hasattr(self, '_' + self.__class__.__name__+ '__gsm'): return "" else: return self.__gsm security.declareProtected(perm_view, 'get_quote') def get_quote(self): """Get quote.""" if not hasattr(self, '_' + self.__class__.__name__+ '__quote'): return "" else: return self.__quote security.declareProtected(perm_view, 'render_quote') def render_quote(self): """Render quote.""" return render( self.get_quote(), legal_tags=normal_entry_tags) security.declareProtected(perm_view, 'get_background') def get_background(self): """Get background.""" if not hasattr(self, '_' + self.__class__.__name__+ '__background'): return "" else: return self.__background security.declareProtected(perm_view, 'render_background') def render_background(self): """Render background.""" return render( self.get_background(), legal_tags=normal_entry_tags) security.declareProtected(perm_view, 'get_personal_interests') def get_personal_interests(self): """Get personal interests.""" if not hasattr(self, '_' + self.__class__.__name__+ '__personal_interests'): return "" else: return self.__personal_interests security.declareProtected(perm_view, 'render_personal_interests') def render_personal_interests(self): """Render personal interests.""" return render( self.get_personal_interests(), legal_tags=normal_entry_tags) security.declareProtected(perm_view, 'get_professional_interests') def get_professional_interests(self): """Get professional interests.""" if not hasattr(self, '_' + self.__class__.__name__+ '__professional_interests'): return "" else: return self.__professional_interests security.declareProtected(perm_view, 'render_professional_interests') def render_professional_interests(self): """Render professional interests.""" return render( self.get_professional_interests(), legal_tags=normal_entry_tags) security.declareProtected(perm_view, 'get_organization') def get_organization(self): """Get organization.""" if not hasattr(self, '_' + self.__class__.__name__+ '__organization'): return "" else: return self.__organization security.declareProtected(perm_view, 'get_city') def get_city(self): """Get city.""" if not hasattr(self, '_' + self.__class__.__name__+ '__city'): return "" else: return self.__city security.declarePrivate('setUniqId') def setUniqId(self, uniq_id): """ set uniq id to user. It shouldn't be changed and it should be uniq at all times. """ if not uniq_id: raise 'IVA error:', 'uniq id not passed' self.__uniq_id = uniq_id security.declareProtected(perm_manage, 'getUniqId') def getUniqId(self): """ return uniq id. """ return self.__uniq_id security.declareProtected(perm_view, 'get_default_webtop_bgs') def get_default_webtop_bgs(self): """Return a list of default Image objects.""" names = bg_stuff.keys() names.sort() return [eval('self.images.%s' % x) for x in names] security.declarePrivate('last_active') def last_active(self, course_id): """Return time when user was last active.""" return self.Statistics.getUserCourseStat(int(course_id), 'lastAccess', self.get_uname()) security.declareProtected(perm_edit, 'global_last_active') def global_last_active(self): """ Last time when user was active. (any click in IVA) """ val = getUtility(IStatistics).getUserGlobalStat(self.get_uname(), 'lastAccessGlobal') try: val = float(val) except TypeError: if isinstance(val, type(datetime.datetime(1,2,3))): val = time.mktime(val.utctimetuple()) return val return float(getUtility(IStatistics).getUserGlobalStat(self.get_uname(), 'lastAccessGlobal')) def global_last_active_time(self, REQUEST): """ Tekstina """ if self.global_last_active()==0:return "-" return time.strftime(translate(self,'timestamp_format',default="%H:%M %Y-%m-%d"), time.localtime(self.global_last_active())) def is_logged_in(self): """ returns True is user is logged in """ #return self.get_uname() in self.Statistics.active_users() return self.get_uname() in getUtility(IStatistics).active_users() def empty_pwd(self): """Return ...""" return "eightchr" # security.declareProtected(perm_edit, 'empty_pwd') def empty_pwd2(self): """ Return default empty password. Note, user can't use this password.""" if self.getSetting('perm_must_change'): return "wightchr" else: return "eightchr" def empty_pwd1(self): """Return default empty password. Note, user can't use this password.""" if self.getSetting('perm_must_change'): return "magic" else: return 'eightchr' security.declareProtected(perm_edit, 'set_password') def set_password(self, pwd): self.muuda_parool(pwd) #roles = self.acl_users.data.get(self.get_id()).roles #self.acl_users._doChangeUser(self.getId(), pwd, roles, []) security.declareProtected(perm_edit, 'muuda_parool') def muuda_parool(self, uusparool): """ Püütakse kasutajal parool muuta """ kataloog=self.leiaKasutajaKataloog(self.get_id()) if kataloog: kataloog.aq_base.users.updateUserPassword(self.get_id(), uusparool) return 0 security.declareProtected(perm_view, 'has_role') def has_role(self, role): """Has user given role.""" return role in get_roles(self.parent().parent(),self.get_uname()) security.declareProtected(perm_view, 'has_any_role') def has_any_role(self, roles): """Has user any of given role.""" real_roles = get_roles(self,self.get_uname()) for role in roles: if role in real_roles: return 1 return 0 # XXX: FAILS! security.declareProtected('View', 'has_right_to_edit') def has_right_to_edit(self, REQUEST): logged_user = self.parent().get_user_info(self.get_current_user(REQUEST)) if self.has_role('IVAAdmin'): if not logged_user.has_role('IVAAdmin'): return 0 else: # a user with FLEAdmin role can edit do anything (even edit # other user with FLEAdmin role. return 1 elif self.get_id() == logged_user.get_id(): return 1 else: return self.is_power_user( self.get_current_user(REQUEST)) security.declareProtected(perm_edit, 'edit_user_form_handler') def edit_user_form_handler( self, REQUEST, # actual user info data from forms pwd = '', # password pwd_confirm = '', # password confirmation nickname = None, first_name = None, last_name = None, email = None, organization = None, language = None, role = None, delete_my_image = None, photo_upload = None, photo_url = None, group = None, address1 = None, address2 = None, city = None, country = None, homepage = None, phone = None, gsm = None, quote = None, background = None, personal_interests = None, professional_interests = None, webtop_bg_upload=None, default_webtop_bg=None, keel_brauserist=0, email_hinded=0, email_kirjad=0, email_raamat=0, email_teadm=0, email_meedia=0, eventLimit=1, cancel = '', commit = '', ): """User info edit form handler.""" redir_base = 'fle_users/'+self.get_uname() homepage = homepage.strip() if cancel: if REQUEST: REQUEST.RESPONSE.redirect('show_user_info.html') return if not self.has_right_to_edit(REQUEST): raise 'FLE Error', \ 'I am sorry Dave. I am afraid I cannot do that.' errors = [] for s in ('first_name', 'last_name', 'email', 'organization', 'photo_url', 'address1', 'address2', 'city', 'homepage', 'phone', 'gsm'): e = REQUEST.get(s) if e: e = e.strip() REQUEST.set(s, e) # Mandatory for x in ('first_name', 'last_name'): e = REQUEST.get(x) if e and not is_valid_title(e): #XXX: tricky to translate! errors.append(+ x) # Optional for x in ('nickname', 'email', 'organization', 'language', 'address1', 'address2', 'city', 'phone', 'gsm'): e = REQUEST.get(x) if e and not is_valid_title(e): #XXX: tricky to translate! errors.append(x) # These are optional, too. if photo_url and not is_valid_url(photo_url): errors.append('url_to_photo') if homepage and not is_valid_url(homepage): homepage='http://'+homepage if homepage and not is_valid_url(homepage): errors.append('homepage') # FIXME: input_checks: group for x in ('quote', 'background', 'personal_interests', 'professional_interests'): value = REQUEST.get(x) if value and ('<' in value or '>' in value): #XXX: tricky to translate! errors.append(x) # Check that the nick name isn't already taken if nickname: if nickname in \ [x.get_uname() for x in self.fle_users.get_users()]\ or nickname in \ [x.get_nickname() for x in self.fle_users.get_users()]: errors.append('nickname') if len(errors) > 0: # Update photo, because we can't save that to URL. if photo_upload and len(photo_upload.filename) > 0: self.set_photo(photo_upload.read(), photo_upload.headers['content-type']) action = apply( make_action, [redir_base+'/edit_user_form.html'] + [(x, REQUEST.get(x)) for x in ('first_name', 'last_name', 'email', 'homepage', 'organization', 'language', 'role', 'photo_url', 'address1', 'address2', 'city', 'country', 'phone', 'gsm', 'quote', 'background', 'personal_interests', 'professional_interests')]) return self.restrictedTraverse('message_dialog.html')( self, REQUEST, title='Invalid input', message= translate(self,'Invalid fields') + ": '" + \ "' , '".join(errors) + "'", action=action) if nickname and not hasattr(self,'nickname'): self.nickname=nickname self.seaKeelBrauserist(keel_brauserist) if webtop_bg_upload and len(webtop_bg_upload.filename) > 0: self.webtop.set_webtop_bg_from_image_data(webtop_bg_upload.read()) elif default_webtop_bg: self.webtop.set_webtop_bg_from_default_image(default_webtop_bg) if not email_hinded: email_hinded = 0 if not email_kirjad: email_kirjad =0 if not email_raamat: email_raamat = 0 if not email_teadm: email_teadm = 0 if not email_meedia: email_meedia = 0 self.edit_info( first_name, last_name, email, organization, language, delete_my_image, photo_upload, photo_url, group, address1, address2, city, country, homepage, phone, gsm, quote, background, personal_interests, professional_interests, email_hinded, email_kirjad, email_raamat, email_teadm, email_meedia,eventLimit) muutis_parooli = 0 if pwd and (pwd != self.empty_pwd()): # change password if pwd == pwd_confirm: #self.set_password(pwd) if not self.getSetting('perm_pass'): self.muuda_parool(pwd) else: pass if hasattr(self,'perm_must_change'): if self.perm_must_change == 1: muutis_parooli = 1 self.perm_must_change = 0 else: if REQUEST: return self.restrictedTraverse('message_dialog.html')( self, REQUEST, title='Error', message='password mismatch', action=redir_base+'/edit_user_form.html') if first_name == '': return self.restrictedTraverse('message_dialog.html')( self,REQUEST, title='Error', message=translate(self,'Enter correct ') + translate(self,'first name'), action=redir_base+'/edit_user_form.html') if last_name == '': return self.restrictedTraverse('message_dialog.html')( self,REQUEST, title='Error', message=translate(self,'Enter correct ') + translate(self,'last_name'), action=redir_base+'/edit_user_form.html') if not re.match("^.+@.+\..{2,3}$",email): return self.restrictedTraverse('message_dialog.html')( self, REQUEST, title = 'Error', message=translate(self, 'Enter correct ') + translate(self, 'email'), action=redir_base+'/edit_user_form.html') if REQUEST: if muutis_parooli: REQUEST.RESPONSE.redirect('organizer_index') else: REQUEST.RESPONSE.redirect('show_user_info.html') # Implementation of edit_user_form_handler without http code. security.declarePrivate('edit_info') def edit_info( self, first_name = None, last_name = None, email = None, organization = None, language = None, delete_my_image = None, photo_upload = None, photo_url = None, group = None, address1 = None, address2 = None, city = None, country = None, homepage = None, phone = None, gsm = None, quote = None, background = None, personal_interests = None, professional_interests = None, email_hinded = None, email_kirjad = None, email_raamat = None, email_teadm = None, email_meedia = None, eventLimit = 1 ): """Commits changes in userinfo object.""" if first_name != None: self.set_first_name(first_name) if last_name != None: self.set_last_name(last_name) if email != None: self.set_email(email) if organization != None: self.set_organization(organization) if language != None: self.set_language(language) if group != None: self.set_group(group) if address1 != None: self.set_address1(address1) if address2 != None: self.set_address2(address2) if city != None: self.set_city(city) if country != None: self.set_country(country) if homepage != None: self.set_homepage(homepage) if phone != None: self.set_phone(phone) if gsm != None: self.set_gsm(gsm) if quote != None: self.set_quote(quote) if background != None: self.set_background(background) if personal_interests != None: self.set_personal_interests(personal_interests) if professional_interests != None: self.set_professional_interests(professional_interests) if email_hinded != None: self.email_hinded = int(email_hinded) if email_kirjad != None: self.email_kirjad = int(email_kirjad) if email_raamat != None: self.email_raamat = int(email_raamat) if email_teadm != None: self.email_teadm = int(email_teadm) if email_meedia != None: self.email_meedia = int(email_meedia) if delete_my_image == 'delete_my_image': # delete image self.remove_photo() if photo_upload != None: if hasattr(photo_upload,'filename') and \ len(photo_upload.filename) > 0: photo_data = photo_upload.read() self.set_photo(photo_data,photo_upload.headers['content-type']) #return if photo_url != None and photo_url != '' and photo_url != 'http://': photo_data = get_url(photo_url) self.set_photo(photo_data) self.set_event_limit(eventLimit) self.default_catalog = 'userinfo_zcatalog' self.reindex_object() security.declareProtected(perm_edit,'set_event_limit') def set_event_limit(self,eventLimit): self.eventLimit = int(eventLimit) return self.eventLimit security.declareProtected(perm_edit,'get_event_limit') def get_event_limit(self): """ return week """ return getattr(self.aq_self, 'eventLimit', 1) def kysiKirjadeKataloog(self): "lisatakse kui pole" return self.kirjad def checkFitTimelimit(self,event,tstart,tend): """ check if given event fits time limits """ if tstart