def dyn_usersettings_submit(param, request): """ ExtDirect method for submitting user setting section form. """ sess = DBSession() s = None if 'auth.settings' in request.session: s = request.session['auth.settings'] for (ust, us) in sess \ .query(UserSettingType, UserSetting) \ .outerjoin(UserSetting, and_( UserSettingType.id == UserSetting.type_id, UserSetting.user_id == request.user.id )) \ .filter(UserSettingType.name.in_(param.keys())): if ust.name in param: if us: us.value = ust.param_to_db(param[ust.name]) else: us = UserSetting() us.user = request.user us.type = ust us.value = ust.param_to_db(param[ust.name]) sess.add(us) if s: s[ust.name] = ust.parse_param(param[ust.name]) if s: request.session['auth.settings'] = s return { 'success' : True }
def xop_request(ctx, request): # TODO: add optional redirect-to-site? if not ctx.can_access(request): raise HTTPForbidden('Access Denied') gw = ctx.get_gateway() if (not gw) or (not hasattr(gw, 'process_request')): raise HTTPForbidden('Access Denied') if not callable(gw.process_request): raise HTTPForbidden('Access Denied') try: sess = DBSession() xoplist = gw.process_request(request, sess) except Exception as e: # TODO: cancel and log? raise HTTPForbidden('Access Denied') for xop in xoplist: ctx.check_operation(xop) sess.add(xop) if hasattr(gw, 'generate_response') and callable(gw.generate_response): return gw.generate_response(request, xoplist) resp = Response(body='OK', content_type='text/plain', charset='UTF-8') return resp
def dav_create(self, req, name, rtype=None, props=None, data=None): # TODO: externalize type resolution user = req.user sess = DBSession() if rtype and (dprops.COLLECTION in rtype): obj = FileFolder( user_id=user.id, group_id=user.group_id, name=name, parent=None, rights=F_DEFAULT_DIRS ) sess.add(obj) else: obj = File( user_id=user.id, group_id=user.group_id, filename=name, name=name, folder=None, rights=F_DEFAULT_FILES ) sess.add(obj) if data is not None: # TODO: detect type of data (fd / buffer) obj.set_from_file(data, user, sess) if props and (dprops.CONTENT_TYPE in props): obj.mime_type = props[dprops.CONTENT_TYPE] if props: if dprops.CREATION_DATE in props: obj.creation_time = props[dprops.CREATION_DATE] if dprops.LAST_MODIFIED in props: obj.modification_time = props[dprops.LAST_MODIFIED] return (obj, False)
def file_ul(request): sess = DBSession() try: ff_id = request.POST['ffid'] except KeyError: ff_id = None folder = None if ff_id: ff_id = int(ff_id) folder = sess.query(FileFolder).get(ff_id) if folder and not folder.can_write(request.user): raise ValueError('Folder access denied') for fo in request.POST.getall('file'): obj = File( user_id=request.user.id, user=request.user, group_id=request.user.group.id, group=request.user.group, rights=F_DEFAULT_FILES ) if fo.filename: obj.name = obj.filename = fo.filename obj.folder = folder sess.add(obj) obj.set_from_file(fo.file, request.user, sess) res = Response(html_escape(json.dumps({ 'success' : True, 'msg' : 'File(s) uploaded' }), False)) res.headerlist.append(('X-Frame-Options', 'SAMEORIGIN')) return res
def client_upload(request): csrf = request.POST.get('csrf', '') mode = request.POST.get('mode', '') if not mode: raise HTTPForbidden('Invalid upload use') if csrf != request.get_csrf(): raise HTTPForbidden('Error uploading file') sess = DBSession() # FIXME: add folder cfg tpldef = [] for fo in request.POST.getall('files'): obj = File() if fo.filename: obj.name = obj.filename = fo.filename sess.add(obj) obj.set_from_file(fo.file, None, sess) signal = request.run_hook('access.cl.upload', obj, mode, request, sess, tpldef) if True not in signal: tpldef.append({ 'name' : obj.filename, 'size' : obj.size, 'error' : _('Error uploading file') }) sess.delete(obj) tpldef = { 'files' : tpldef } request.run_hook('access.cl.tpldef.upload', tpldef, request) return tpldef
def _wizcb_submit_hdl(wiz, em, step, act, val, req): xcls = cls if isinstance(xcls, str): xcls = _name_to_class(xcls) sess = DBSession() cfg = get_current_registry().settings fieldIDs = json.loads(val['field_id']) fieldlist = val['field'] templateName = val['template'] templId = val['templ_id'] for fid in fieldIDs: resvalue = {'templ_id' : templId, 'field_id' : fid, 'template' : templateName, 'field' : sess.query(PDNSFieldType).filter(PDNSFieldType.id==fid).first() } em = ExtModel(xcls) obj = xcls() em.set_values(obj, resvalue, req, True) sess.add(obj) sess.flush() print("TROLOLO") return { 'do' : 'close', 'reload' : True }
def client_issue_append(ctx, req): loc = req.localizer cfg = req.registry.settings if not asbool(cfg.get('netprofile.client.ticket.enabled', True)): raise HTTPForbidden(detail=_('Issues view is disabled')) errors = {} if ctx.archived: req.session.flash({ 'class': 'danger', 'text': loc.translate( _('This ticket is archived. You can\'t append to it.')) }) return HTTPSeeOther(location=req.route_url('tickets.cl.issues', traverse=(ctx.id, 'view'))) if 'submit' in req.POST: csrf = req.POST.get('csrf', '') comments = req.POST.get('comments', '') if csrf != req.get_csrf(): errors['csrf'] = _a('Error submitting form') elif not comments: errors['comments'] = _a('Invalid field length') if len(errors) == 0: sess = DBSession() ch = TicketChange() ch.ticket = ctx ch.from_client = True ch.show_client = True ch.comments = comments sess.add(ch) req.session.flash({ 'text': loc.translate( _('Your comment was successfully appended to the issue')) }) return HTTPSeeOther(location=req.route_url( 'tickets.cl.issues', traverse=(ctx.id, 'view'))) tpldef = { 'crumbs': [{ 'text': loc.translate(_('My Issues')), 'url': req.route_url('tickets.cl.issues', traverse=()) }, { 'text': loc.translate(_('View Issue #%d')) % ctx.id, 'url': req.route_url('tickets.cl.issues', traverse=(ctx.id, 'view')) }, { 'text': loc.translate(_('Append Comment to Issue #%d')) % ctx.id }], 'ticket': ctx, 'errors': {err: loc.translate(errors[err]) for err in errors} } req.run_hook('access.cl.tpldef', tpldef, req) req.run_hook('access.cl.tpldef.issue.append', tpldef, req) return tpldef
def _wizcb_submit_hdl(wiz, em, step, act, val, req): xcls = cls if isinstance(xcls, str): xcls = _name_to_class(xcls) sess = DBSession() fieldIDs = json.loads(val['field_id']) templateName = val['template'] templId = val['templ_id'] for fid in fieldIDs: resvalue = { 'templ_id': templId, 'field_id': fid, 'template': templateName, 'field': sess.query(PDNSFieldType).filter( PDNSFieldType.id == fid).first() } em = ExtModel(xcls) obj = xcls() em.set_values(obj, resvalue, req, True) sess.add(obj) sess.flush() print("TROLOLO") return {'do': 'close', 'reload': True}
def client_promise(ctx, request): loc = get_localizer(request) csrf = request.POST.get('csrf', '') diff = request.POST.get('diff', '') if 'submit' in request.POST: sess = DBSession() if csrf != request.get_csrf(): request.session.flash({ 'text' : loc.translate(_('Error submitting form')), 'class' : 'danger' }) return HTTPSeeOther(location=request.route_url('stashes.cl.accounts', traverse=())) fp = FuturePayment() fp.stash = ctx fp.entity = request.user.parent fp.origin = FuturePaymentOrigin.user fp.difference = diff sess.add(fp) request.session.flash({ 'text' : loc.translate(_('Successfully added new promised payment')) }) return HTTPSeeOther(location=request.route_url('stashes.cl.accounts', traverse=())) request.session.flash({ 'text' : loc.translate(_('Error submitting form')), 'class' : 'danger' }) return HTTPSeeOther(location=request.route_url('stashes.cl.accounts', traverse=()))
def dyn_usersettings_submit(param, request): """ ExtDirect method for submitting user settings form. """ sess = DBSession() mmgr = request.registry.getUtility(IModuleManager) cached = None if 'auth.settings' in request.session: cached = request.session['auth.settings'] all_settings = mmgr.get_settings('user') values = dict( (s.name, s) for s in sess.query(UserSetting).filter(UserSetting.user == request.user) ) for moddef, sections in all_settings.items(): for sname, section in sections.items(): if section.read_cap and not request.has_permission(section.read_cap): continue for setting_name, setting in section.items(): if setting.read_cap and not request.has_permission(setting.read_cap): continue if setting.write_cap and not request.has_permission(setting.write_cap): continue fullname = '%s.%s.%s' % (moddef, sname, setting_name) old_value = setting.default if fullname in values: old_value = setting.parse_param(values[fullname].value) new_value = old_value if fullname in param: new_value = setting.parse_param(param[fullname]) if new_value == setting.default: if fullname in values: sess.delete(values[fullname]) del values[fullname] if cached: cached[fullname] = setting.default continue if new_value != old_value: if fullname in values: values[fullname].value = setting.format_param(new_value) else: values[fullname] = UserSetting( user=request.user, name=fullname, value=setting.format_param(new_value) ) sess.add(values[fullname]) if cached: cached[fullname] = new_value if cached: request.session['auth.settings'] = cached return { 'success' : True }
def clone(self, req, ctx, recurse=True, _flush=True): sess = DBSession() obj = ctx.dav_clone(req) sess.add(obj) if recurse: for ch in self.children(ctx): newch = self.clone(req, ch, recurse, False) obj.dav_append(req, newch, ch.__name__) return obj
def _wizcb_future_submit(wiz, em, step, act, val, req): sess = DBSession() obj = FuturePayment() em.set_values(obj, val, req, True) sess.add(obj) return { 'do' : 'close', 'reload' : True }
def dav_sync_token(self): varname = 'DAV:SYNC:ABC:%u' % (self.user.id,) try: var = NPVariable.get_ro(varname) except NoResultFound: sess = DBSession() cvar = NPVariable.get_ro('DAV:SYNC:PLUG:UABOOKS') var = NPVariable(name=varname, integer_value=cvar.integer_value) sess.add(var) return var.integer_value
def _wizcb_aent_submit(wiz, em, step, act, val, req): sess = DBSession() em = ExtModel(AccessEntity) obj = AccessEntity() # Work around field name clash if 'state' in val: del val['state'] em.set_values(obj, val, req, True) sess.add(obj) return {'do': 'close', 'reload': True}
def _cal_events_create(params, req): sess = DBSession() ev = Event() ev.creation_time = dt.datetime.now() if not _ev_set(sess, ev, params, req): del ev return False ev.user = req.user sess.add(ev) return True
def _wizcb_stashio_submit(wiz, em, step, act, val, req): sess = DBSession() obj = StashIO() em.set_values(obj, val, req, True) sess.add(obj) if obj.difference: stash = sess.query(Stash).get(obj.stash_id) if stash: stash.amount += obj.difference return {"do": "close", "reload": True}
def _check_session(event): request = event.request if not isinstance(event.policy, SessionAuthenticationPolicy): return user = request.user route_name = None if request.matched_route: route_name = request.matched_route.name # TODO: unhardcode excluded routes if route_name in {'core.login', 'debugtoolbar', 'core.logout.direct', 'core.wellknown'}: return if not user: _goto_login(request) settings = request.registry.settings skey = settings.get('redis.sessions.cookie_name') if not skey: skey = settings.get('session.key') assert skey is not None, 'Session cookie name does not exist' sess = DBSession() sname = request.cookies.get(skey) if sname: now = dt.datetime.now() oldsess = True try: npsess = sess.query(NPSession).filter( NPSession.session_name == sname).one() except NoResultFound: npsess = user.generate_session(request, sname, now) if npsess is None: _goto_login(request) oldsess = False sess.add(npsess) if oldsess and not npsess.check_request(request, now): _goto_login(request) pw_age = request.session.get('sess.pwage', 'ok') if pw_age == 'force': # TODO: unhardcode excluded routes if route_name not in {'extrouter', 'extapi', 'core.home', 'core.js.webshell'}: _goto_login(request) npsess.update_time(now) request.np_session = npsess else: _goto_login(request)
def lock(self): req = self.req ctx = req.context req.dav.user_acl(req, ctx, dprops.ACL_WRITE_CONTENT) path = req.dav.ctx_path(ctx) str_path = '/'.join(path) locks = req.dav.get_locks(path) lock = None if req.body: # New lock oldlock = None for oldlock in locks: if oldlock.scope == DAVLock.SCOPE_EXCLUSIVE: raise dav.DAVConflictingLockError(lock=oldlock) lreq = dav.DAVLockRequest(req) lock = lreq.get_lock(DAVLock) if oldlock and (lock.scope != DAVLock.SCOPE_SHARED): raise dav.DAVConflictingLockError(lock=oldlock) lock.uri = str_path lock.depth = req.dav.get_http_depth(req) if isinstance(ctx, File): lock.file = ctx else: # Refreshing old lock ifh = self.get_if() if not ifh: raise dav.DAVBadRequestError('No If: headers supplied in LOCK refresh request.') try: for oldlock in locks: for ifobj in ifh: for token in ifobj['tokens']: if oldlock.test_token(token['tok']): lock = oldlock raise StopIteration except StopIteration: pass if lock is None: if len(locks): raise dav.DAVLockedError('Resource is locked.', lock=locks[0]) else: raise dav.DAVBadRequestError('New LOCK request must be accompanied by a request body.') lock.refresh(req.dav.get_http_timeout(req)) if req.body: sess = DBSession() sess.add(lock) resp = dav.DAVLockResponse(lock=lock, request=req, new_file=False) resp.make_body() return resp
def apply_async(self, entry, producer=None, advance=True, **kwargs): res = super(Scheduler, self).apply_async(entry, producer, advance, **kwargs) model = entry.model if model.log_executions: sess = DBSession() log = model.new_result(res) sess.add(log) self._pending_results[log.celery_id] = res transaction.commit() return res
def setUp(self): self.config = testing.setUp() from sqlalchemy import create_engine engine = create_engine('sqlite://') from .models import ( Base, MyModel, ) DBSession.configure(bind=engine) Base.metadata.create_all(engine) with transaction.manager: model = MyModel(name='one', value=55) DBSession.add(model)
def _wizcb_aent_submit(wiz, em, step, act, val, req): sess = DBSession() em = ExtModel(AccessEntity) obj = AccessEntity() # Work around field name clash if 'state' in val: del val['state'] em.set_values(obj, val, req, True) sess.add(obj) return { 'do' : 'close', 'reload' : True }
def _wizcb_submit_hdl(wiz, em, step, act, val, req): xcls = cls if isinstance(xcls, str): xcls = _name_to_class(xcls) sess = DBSession() em = ExtModel(xcls) obj = xcls() em.set_values(obj, val, req, True) sess.add(obj) return { 'do' : 'close', 'reload' : True }
def ff_tree_create(params, request): recs = [] sess = DBSession() user = request.user total = 0 for rec in params.get('records', ()): ff_name = rec.get('text') ff_parent = rec.get('parentId') # TODO: support changing uid/gid and rights, maybe? if not ff_name: raise ValueError('Empty folder names are not supported') if ff_parent and (ff_parent != 'root'): ff_parent = int(ff_parent) else: ff_parent = None ff = FileFolder(user=user, group=user.group) ff.name = ff_name root_ff = user.group.effective_root_folder if root_ff and (ff_parent is None): raise ValueError('Folder access denied') if ff_parent: ffp = sess.query(FileFolder).get(ff_parent) if ffp is None: raise KeyError('Unknown parent folder ID %d' % ff_parent) if (not ffp.can_write(user)) or (not ffp.can_traverse_path(user)): raise ValueError('Folder access denied') if root_ff and (not ffp.is_inside(root_ff)): raise ValueError('Folder access denied') ff.parent = ffp elif not user.root_writable: raise ValueError('Folder access denied') sess.add(ff) sess.flush() recs.append({ 'id' : str(ff.id), 'parentId' : str(ff.parent.id) if ff.parent else 'root', 'text' : ff.name, 'xhandler' : 'NetProfile.controller.FileBrowser', 'allow_read' : ff.can_read(user), 'allow_write' : ff.can_write(user), 'allow_traverse' : ff.can_traverse(user), 'parent_write' : ff.parent.can_write(user) if ff.parent else user.root_writable }) total += 1 return { 'success' : True, 'records' : recs, 'total' : total }
def _check_session(event): request = event.request if not isinstance(event.policy, SessionAuthenticationPolicy): return user = request.user route_name = None if request.matched_route: route_name = request.matched_route.name # TODO: unhardcode excluded routes if route_name in ('core.login', 'debugtoolbar', 'core.logout.direct', 'core.wellknown'): return if not user: _goto_login(request) settings = request.registry.settings skey = settings.get('redis.sessions.cookie_name') if not skey: skey = settings.get('session.key') assert skey is not None, 'Session cookie name does not exist' sess = DBSession() sname = request.cookies.get(skey) if sname: now = dt.datetime.now() oldsess = True try: npsess = sess.query(NPSession).filter( NPSession.session_name == sname).one() except NoResultFound: npsess = user.generate_session(request, sname, now) if npsess is None: _goto_login(request) oldsess = False sess.add(npsess) if oldsess and (not npsess.check_request(request, now)): _goto_login(request) pw_age = request.session.get('sess.pwage', 'ok') if pw_age == 'force': # TODO: unhardcode excluded routes if route_name not in ('extrouter', 'extapi', 'core.home', 'core.js.webshell'): _goto_login(request) npsess.update_time(now) request.np_session = npsess else: _goto_login(request)
def _wizcb_stashio_submit(wiz, step, act, val, req): sess = DBSession() em = ExtModel(StashIO) obj = StashIO() em.set_values(obj, val, req, True) sess.add(obj) if obj.difference: stash = sess.query(Stash).get(obj.stash_id) if stash: stash.amount += obj.difference return { 'do' : 'close', 'reload' : True }
def client_issue_append(ctx, req): loc = req.localizer cfg = req.registry.settings if not asbool(cfg.get('netprofile.client.ticket.enabled', True)): raise HTTPForbidden(detail=_('Issues view is disabled')) errors = {} if ctx.archived: req.session.flash({ 'class' : 'danger', 'text' : loc.translate(_('This ticket is archived. You can\'t append to it.')) }) return HTTPSeeOther(location=req.route_url('tickets.cl.issues', traverse=(ctx.id, 'view'))) if 'submit' in req.POST: csrf = req.POST.get('csrf', '') comments = req.POST.get('comments', '') if csrf != req.get_csrf(): errors['csrf'] = _a('Error submitting form') elif not comments: errors['comments'] = _a('Invalid field length') if len(errors) == 0: sess = DBSession() ch = TicketChange() ch.ticket = ctx ch.from_client = True ch.show_client = True ch.comments = comments sess.add(ch) req.session.flash({ 'text' : loc.translate(_('Your comment was successfully appended to the issue')) }) return HTTPSeeOther(location=req.route_url('tickets.cl.issues', traverse=(ctx.id, 'view'))) tpldef = { 'crumbs' : [{ 'text' : loc.translate(_('My Issues')), 'url' : req.route_url('tickets.cl.issues', traverse=()) }, { 'text' : loc.translate(_('View Issue #%d')) % ctx.id, 'url' : req.route_url('tickets.cl.issues', traverse=(ctx.id, 'view')) }, { 'text' : loc.translate(_('Append Comment to Issue #%d')) % ctx.id }], 'ticket' : ctx, 'errors' : {err: loc.translate(errors[err]) for err in errors} } req.run_hook('access.cl.tpldef', tpldef, req) req.run_hook('access.cl.tpldef.issue.append', tpldef, req) return tpldef
def dyn_globalsettings_submit(param, request): """ ExtDirect method for submitting global settings form. """ sess = DBSession() mmgr = request.registry.getUtility(IModuleManager) all_settings = mmgr.get_settings('global') values = dict( (s.name, s) for s in sess.query(GlobalSetting) ) for moddef, sections in all_settings.items(): for sname, section in sections.items(): if section.read_cap and not request.has_permission(section.read_cap): continue for setting_name, setting in section.items(): if setting.read_cap and not request.has_permission(setting.read_cap): continue if setting.write_cap and not request.has_permission(setting.write_cap): continue fullname = '%s.%s.%s' % (moddef, sname, setting_name) old_value = setting.default if fullname in values: old_value = setting.parse_param(values[fullname].value) new_value = old_value if fullname in param: new_value = setting.parse_param(param[fullname]) # We don't delete global settings if their values are default # ones because we need the values in other places: procedures, # SQL events, triggers etc. if new_value != old_value: if fullname in values: values[fullname].value = setting.format_param(new_value) else: values[fullname] = GlobalSetting( name=fullname, value=setting.format_param(new_value) ) sess.add(values[fullname]) return { 'success' : True }
def _wizcb_stashio_submit(wiz, em, step, act, val, req): sess = DBSession() obj = StashIO() em.set_values(obj, val, req, True) sess.add(obj) stash = None if obj.difference: stash = sess.query(Stash).get(obj.stash_id) if stash: stash.amount += obj.difference ret = { 'do' : 'close', 'reload' : True } if stash is not None: ret['affects'] = ( ('stashes', 'StashIO'), ('stashes', 'Stash', obj.stash_id), ) return ret
def client_promise(ctx, request): loc = get_localizer(request) csrf = request.POST.get("csrf", "") diff = request.POST.get("diff", "") if "submit" in request.POST: sess = DBSession() if csrf != request.get_csrf(): request.session.flash({"text": loc.translate(_("Error submitting form")), "class": "danger"}) return HTTPSeeOther(location=request.route_url("stashes.cl.accounts", traverse=())) fp = FuturePayment() fp.stash = ctx fp.entity = request.user.parent fp.origin = FuturePaymentOrigin.user fp.difference = diff sess.add(fp) request.session.flash({"text": loc.translate(_("Successfully added new promised payment"))}) return HTTPSeeOther(location=request.route_url("stashes.cl.accounts", traverse=())) request.session.flash({"text": loc.translate(_("Error submitting form")), "class": "danger"}) return HTTPSeeOther(location=request.route_url("stashes.cl.accounts", traverse=()))
def client_oauth_register(request, regdict): nxt = request.route_url('access.cl.home') loc = get_localizer(request) headers = None #if authenticated_userid(request): # return HTTPSeeOther(location=nxt) cfg = request.registry.settings rate_id = int(cfg.get('netprofile.client.registration.rate_id', 1)) state_id = int(cfg.get('netprofile.client.registration.state_id', 1)) errors = {} sess = DBSession() login = regdict.get('username', None) passwd = regdict.get('password', None) email = regdict.get('email', None) name_family = regdict.get('familyname', '') name_given = regdict.get('givenname', '') ### !!!!! What if user changes his password in out database?! if login is not None and passwd is not None: q = sess.query(AccessEntity).filter(AccessEntity.nick == login, AccessEntity.access_state != AccessState.block_inactive.value) if q is not None: for user in q: if user.password == passwd: headers = remember(request, login) return headers if headers is None: ent = PhysicalEntity() ent.nick = login ent.email = email ent.name_family = name_family ent.name_given = name_given ent.state_id = state_id stash = Stash() stash.entity = ent stash.name = loc.translate(_('Primary Account')) acc = AccessEntity() acc.nick = login acc.password = passwd acc.stash = stash acc.rate_id = rate_id acc.state_id = state_id ent.children.append(acc) sess.add(ent) sess.add(stash) sess.add(acc) sess.flush() headers = remember(request, login) return headers else: return False
def client_promise(ctx, request): loc = request.localizer csrf = request.POST.get('csrf', '') diff = request.POST.get('diff', '') if 'submit' in request.POST: sess = DBSession() if csrf != request.get_csrf(): request.session.flash({ 'text': loc.translate(_('Error submitting form')), 'class': 'danger' }) return HTTPSeeOther( location=request.route_url('stashes.cl.accounts', traverse=())) fp = FuturePayment() fp.stash = ctx fp.entity = request.user.parent fp.origin = FuturePaymentOrigin.user fp.difference = diff sess.add(fp) request.session.flash({ 'text': loc.translate(_('Successfully added new promised payment')) }) return HTTPSeeOther( location=request.route_url('stashes.cl.accounts', traverse=())) request.session.flash({ 'text': loc.translate(_('Error submitting form')), 'class': 'danger' }) return HTTPSeeOther( location=request.route_url('stashes.cl.accounts', traverse=()))
def _auth_to_db(event): request = event.request if not request.matched_route: return rname = request.matched_route.name if rname[0] == '_': return if request.method == 'OPTIONS': return sess = DBSession() user = request.user if user: sess.execute(SetVariable('accessuid', user.id)) sess.execute(SetVariable('accessgid', user.group_id)) sess.execute(SetVariable('accesslogin', user.login)) skey = request.registry.settings.get('redis.sessions.cookie_name') if not skey: skey = request.registry.settings.get('session.key') assert skey is not None, 'Session cookie name does not exist' sname = request.cookies.get(skey) if sname: try: npsess = sess.query(NPSession).filter(NPSession.session_name == sname).one() npsess.update_time() except NoResultFound: npsess = user.generate_session(request, sname) sess.add(npsess) request.np_session = npsess else: sess.execute(SetVariable('accessuid', 0)) sess.execute(SetVariable('accessgid', 0)) sess.execute(SetVariable('accesslogin', '[GUEST]'))
def createMailBox(request): loc = get_localizer(request) cfg = request.registry.settings sess = DBSession() errmess = None csrf = request.POST.get('csrf', '') access_user = sess.query(AccessEntity).filter_by(nick=str(request.user)).first() admindomains = sess.query(PostfixDomainAdmins).filter_by(username=str(request.user)) if csrf != request.get_csrf(): request.session.flash({ 'text' : loc.translate(_('Error submitting form')), 'class' : 'danger' }) return HTTPSeeOther(location=request.route_url('postfix.cl.mail')) else: domain_name = request.POST.get('mbDomain', None) domain_descr = request.POST.get('mbDomainDescription', None) username = request.POST.get('mbUsername', None) mailbox_name = request.POST.get('mbName', None) mailbox_password = request.POST.get('mbPassword', None) if domain_name and username: if username == access_user.nick: if mailbox_name and mailbox_password: newmailbox = PostfixMailbox( username=username, password=mailbox_password, name=mailbox_name, domain=domain_name ) sess.add(newmailbox) sess.flush() else: if domain_name not in [ad.username for ad in admindomains]: newdomainadmin = PostfixDomainAdmins(username=username, domain=domain_name) newdomain = PostfixDomain(domain=domain_name, description=domain_descr) sess.add(newdomainadmin) sess.add(newdomain) sess.flush() return HTTPSeeOther(location=request.route_url('postfix.cl.mail'))
def notfound_lock(self): # TODO: DRY, unify this with normal lock # TODO: ACL req = self.req path = req.dav.path(req.url) str_path = '/'.join(path) locks = req.dav.get_locks(path) lock = None if req.body: # New lock oldlock = None for oldlock in locks: if oldlock.scope == DAVLock.SCOPE_EXCLUSIVE: raise dav.DAVConflictingLockError(lock=oldlock) lreq = dav.DAVLockRequest(req) lock = lreq.get_lock(DAVLock) if oldlock and (lock.scope != DAVLock.SCOPE_SHARED): raise dav.DAVConflictingLockError(lock=oldlock) lock.uri = str_path lock.depth = req.dav.get_http_depth(req) else: # Refreshing old lock ifh = self.get_if() if not ifh: raise dav.DAVBadRequestError('No If: headers supplied in LOCK refresh request.') try: for oldlock in locks: for ifobj in ifh: for token in ifobj['tokens']: if oldlock.test_token(token['tok']): lock = oldlock raise StopIteration except StopIteration: pass if lock is None: if len(locks): raise dav.DAVLockedError('Resource is locked.', lock=locks[0]) else: raise dav.DAVBadRequestError('New LOCK request must be accompanied by a request body.') if not req.view_name: # TODO: find proper DAV error to put here raise Exception('Invalid file name (empty file names are not allowed).') if len(req.subpath) > 0: # TODO: find proper DAV error to put here raise Exception('Invalid file name (slashes are not allowed).') req.dav.user_acl(req, req.context, dprops.ACL_BIND) creator = getattr(req.context, 'dav_create', None) if creator is None: raise dav.DAVNotImplementedError('Unable to create child node.') with io.BytesIO(b'') as bio: obj, modified = creator(req, req.view_name, None, None, bio) # TODO: handle IOErrors, handle non-seekable request body if isinstance(obj, File): lock.file = obj lock.refresh(req.dav.get_http_timeout(req)) if req.body: sess = DBSession() sess.add(lock) resp = dav.DAVLockResponse(lock=lock, request=req, new_file=True) resp.make_body() return resp
def client_issue_new(ctx, req): loc = req.localizer cfg = req.registry.settings if not asbool(cfg.get('netprofile.client.ticket.enabled', True)): raise HTTPForbidden(detail=_('Issues view is disabled')) origin_id = int(cfg.get('netprofile.client.ticket.origin_id', 0)) user_id = int(cfg.get('netprofile.client.ticket.assign_uid', 0)) group_id = int(cfg.get('netprofile.client.ticket.assign_gid', 0)) errors = {} sess = DBSession() ent = req.user.parent states = sess.query(TicketState)\ .filter(TicketState.is_start == True, TicketState.allow_client == True) if 'submit' in req.POST: csrf = req.POST.get('csrf', '') name = req.POST.get('name', '') descr = req.POST.get('descr', '') state = int(req.POST.get('state', 0)) if csrf != req.get_csrf(): errors['csrf'] = _a('Error submitting form') else: l = len(name) if (l == 0) or (l > 254): errors['name'] = _a('Invalid field length') for s in states: if s.id == state: state = s break else: errors['state'] = _('Invalid issue type') if len(errors) == 0: tkt = Ticket() tkt.name = name tkt.state = state tkt.entity = ent tkt.show_client = True if descr: tkt.description = descr if origin_id: tkt.origin_id = origin_id if user_id: tkt.assigned_user_id = user_id if group_id: tkt.assigned_group_id = group_id sess.add(tkt) sess.flush() req.session.flash( {'text': loc.translate(_('New issue successfully created'))}) return HTTPSeeOther(location=req.route_url( 'tickets.cl.issues', traverse=(tkt.id, 'view'))) tpldef = { 'states': states, 'crumbs': [{ 'text': loc.translate(_('My Issues')), 'url': req.route_url('tickets.cl.issues', traverse=()) }, { 'text': loc.translate(_('New Issue')) }], 'errors': {err: loc.translate(errors[err]) for err in errors} } req.run_hook('access.cl.tpldef', tpldef, req) req.run_hook('access.cl.tpldef.issue.new', tpldef, req) return tpldef
def create_record(request): loc = get_localizer(request) cfg = request.registry.settings sess = DBSession() csrf = request.POST.get('csrf', '') if csrf != request.get_csrf(): request.session.flash({ 'text': loc.translate(_('Error submitting form')), 'class': 'danger' }) return HTTPSeeOther(location=request.route_url('pdns.cl.domains')) else: # get fields related to obtained type and create corresponding fields rectype = request.POST.get('type', None) if rectype != "record" and rectype != "newdomain": # so we are creating some service, domain, mailserver, etc currentvalues = {} hostname = request.POST.get('hostName', None) currentvalues['name'] = hostname # check if we already have such domain name, # if so, return a warning111 # domain_clash = sess.query(func.count('*'))\ # .select_from(PDNSDomain)\ # .filter(PDNSDomain.name == hostname)\ # .scalar() # if domain_clash > 0: # request.session.flash({ # 'text' : loc.translate(_('Domain already exists, please add corresponding records manually')), # 'class' : 'danger' # }) # return HTTPSeeOther(location=request.route_url('pdns.cl.domains')) # if no same domain name warinigs returned, we can continue processing our data # host record # domaintype = request.POST.get('hosttype', 'NATIVE') domainip = request.POST.get('hostValue', None) # if IP-address is not specified, raise a warning if not domainip: request.session.flash({ 'text': loc.translate( _('You need to specify IP address') ), 'class': 'danger' }) return HTTPSeeOther( location=request.route_url('pdns.cl.domains') ) currentvalues['domainip'] = domainip # get the nameservers from the config ns1 = cfg.get('netprofile.client.pdns.ns1') ns2 = cfg.get('netprofile.client.pdns.ns2') currentvalues['nameserver1'] = ns1 currentvalues['nameserver2'] = ns2 currentvalues['ttl'] = 3600 currentvalues['prefix'] = '' currentvalues['name'] = hostname # and here we create our something. # as we have new service type, rectype, we can get all related fields newdomain = sess.query(PDNSDomain).filter( PDNSDomain.name == hostname ).first() service_template = sess.query(PDNSTemplateType).filter( PDNSTemplateType.name == rectype ).join(PDNSTemplate).all() # default values are stored as JSON in the database # if default value is a key of a dictionnary, lookup it's value in the currentvalues dict # else it is a complex value with prefix and value from currentvalues dict, as in jabber contents field # some examples: # Domain NS Record: {"ttl":"86400", "content":"nameserver2"} # Mailserver CNAME Record: {"ttl":"3600", "prefix":"mail", "content":"name"} # Jabber SRV Record: {"ttl":"3600", "prefix":"_xmpp-client._tcp", "content":["5 0 5222 jabber", "name"]} for t in service_template: for f in t.template_fields: defvalues = json.loads(f.defaultvalues) newname = currentvalues['name'] if 'prefix' in defvalues.keys(): newname = "{0}.{1}".format( defvalues['prefix'], newname ) newrtype = f.field.name defcontent = defvalues.get('content', None) if defcontent: if not isinstance(defcontent, list): newcontent = currentvalues.get(defcontent, None) else: def_in_cur = [ defcontent.index(k) for k in filter( lambda x: x in defcontent, currentvalues.keys() ) ] for i in def_in_cur: defcontent[i] = currentvalues[defcontent[i]] newcontent = ".".join(defcontent) else: newcontent = '' newttl = int(defvalues.get('ttl', 3600)) newRecord = PDNSRecord( domain=newdomain, name=newname, rtype=newrtype, content=newcontent, ttl=newttl, ) sess.add(newRecord) sess.flush() elif rectype == "record": ttl = request.POST.get('ttl', None) if ttl == "": ttl = None prio = request.POST.get('prio', None) if prio == "": prio = None newrecord = PDNSRecord( domain_id=int(request.POST.get('domainid', None)), name=request.POST.get('name', None), rtype=request.POST.get('rtype', None), content=request.POST.get('content', None), ttl=ttl, prio=prio ) sess.add(newrecord) sess.flush() elif rectype == "newdomain": hostname = request.POST.get('hostName', '127.0.0.1') hosttype = request.POST.get('hostType', 'NATIVE') domain_clash = sess.query(func.count('*'))\ .select_from(PDNSDomain)\ .filter(PDNSDomain.name == hostname)\ .scalar() if domain_clash > 0: request.session.flash({ 'text': loc.translate( _('Domain already exists,' ' please add corresponding records manually') ), 'class': 'danger' }) return HTTPSeeOther( location=request.route_url('pdns.cl.domains') ) newdomain = PDNSDomain( name=hostname, master='', dtype=hosttype, account=request.POST.get('user', None) ) sess.add(newdomain) sess.flush() return HTTPSeeOther(location=request.route_url( 'pdns.cl.domains', _query=(('created', 1),) ))
def client_register(request): if authenticated_userid(request): return HTTPSeeOther(location=request.route_url('access.cl.home')) cur_locale = locale_neg(request) loc = request.localizer cfg = request.registry.settings comb_js = asbool(cfg.get('netprofile.client.combine_js', False)) can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False)) must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True)) must_recaptcha = asbool(cfg.get('netprofile.client.registration.recaptcha.enabled', False)) min_pwd_len = int(cfg.get('netprofile.client.registration.min_password_length', 8)) rate_id = int(cfg.get('netprofile.client.registration.rate_id', 1)) state_id = int(cfg.get('netprofile.client.registration.state_id', 1)) maillogin = asbool(cfg.get('netprofile.client.email_as_username', False)) csrf = request.POST.get('csrf', '') errors = {} if not can_reg: return HTTPSeeOther(location=request.route_url('access.cl.login')) if must_recaptcha: rc_private = cfg.get('netprofile.client.recaptcha.private_key') rc_public = cfg.get('netprofile.client.recaptcha.public_key') if (not rc_private) or (not rc_public): # TODO: log missing reCAPTCHA keys must_recaptcha = False if 'submit' in request.POST: sess = DBSession() if csrf != request.get_csrf(): errors['csrf'] = _('Error submitting form') elif must_recaptcha: try: rcresp = verify_recaptcha(rc_private, request) except ValueError as e: errors['recaptcha'] = str(e) else: if rcresp and not rcresp.valid: errors['recaptcha'] = rcresp.text() if len(errors) == 0: login = request.POST.get('user', '') passwd = request.POST.get('pass', '') passwd2 = request.POST.get('pass2', '') email = request.POST.get('email', '') name_family = request.POST.get('name_family', '') name_given = request.POST.get('name_given', '') name_middle = request.POST.get('name_middle', '') l = len(email) if (l == 0) or (l > 254): errors['email'] = _('Invalid field length') elif not _re_email.match(email): errors['email'] = _('Invalid e-mail format') if maillogin: login = email else: l = len(login) if (l == 0) or (l > 254): errors['user'] = _('Invalid field length') elif _re_login.match(login): errors['user'] = _('Invalid character used in username') l = len(passwd) if l < min_pwd_len: errors['pass'] = _('Password is too short') elif l > 254: errors['pass'] = _('Password is too long') if passwd != passwd2: errors['pass2'] = _('Passwords do not match') l = len(name_family) if (l == 0) or (l > 254): errors['name_family'] = _('Invalid field length') l = len(name_given) if (l == 0) or (l > 254): errors['name_given'] = _('Invalid field length') l = len(name_middle) if l > 254: errors['name_middle'] = _('Invalid field length') if 'user' not in errors: # XXX: currently we check across all entity types. login_clash = sess.query(func.count('*'))\ .select_from(Entity)\ .filter(Entity.nick == login)\ .scalar() if login_clash > 0: errors['user'] = _('This username is already taken') if len(errors) == 0: ent = PhysicalEntity() ent.nick = login ent.email = email ent.name_family = name_family ent.name_given = name_given if name_middle: ent.name_middle = name_middle ent.state_id = state_id stash = Stash() stash.entity = ent stash.name = loc.translate(_('Primary Account')) acc = AccessEntity() acc.nick = login acc.password = passwd acc.stash = stash acc.rate_id = rate_id acc.state_id = state_id ent.children.append(acc) sess.add(ent) sess.add(stash) sess.add(acc) if must_verify: link_id = int(cfg.get('netprofile.client.registration.link_id', 1)) rand_len = int(cfg.get('netprofile.client.registration.code_length', 20)) queue_mail = asbool(cfg.get('netprofile.client.registration.mail_queue', False)) sender = cfg.get('netprofile.client.registration.mail_sender') acc.access_state = AccessState.block_inactive.value link = AccessEntityLink() link.entity = acc link.type_id = link_id chars = string.ascii_uppercase + string.digits try: rng = random.SystemRandom() except NotImplementedError: rng = random link.value = ''.join(rng.choice(chars) for i in range(rand_len)) link.timestamp = datetime.datetime.now() sess.add(link) mailer = get_mailer(request) tpldef = { 'cur_loc' : cur_locale, 'entity' : ent, 'stash' : stash, 'access' : acc, 'link' : link } request.run_hook('access.cl.tpldef.register.mail', tpldef, request) msg_text = Attachment( data=render('netprofile_access:templates/email_register_plain.mak', tpldef, request), content_type='text/plain; charset=\'utf-8\'', disposition='inline', transfer_encoding='quoted-printable' ) msg_html = Attachment( data=render('netprofile_access:templates/email_register_html.mak', tpldef, request), content_type='text/html; charset=\'utf-8\'', disposition='inline', transfer_encoding='quoted-printable' ) msg = Message( subject=(loc.translate(_('Activation required for user %s')) % login), sender=sender, recipients=(email,), body=msg_text, html=msg_html ) if queue_mail: mailer.send_to_queue(msg) else: mailer.send(msg) return HTTPSeeOther(location=request.route_url('access.cl.regsent')) tpldef = { 'cur_loc' : cur_locale, 'comb_js' : comb_js, 'must_verify' : must_verify, 'must_recaptcha' : must_recaptcha, 'min_pwd_len' : min_pwd_len, 'maillogin' : maillogin, 'errors' : {err: loc.translate(errors[err]) for err in errors} } if must_recaptcha: tpldef['rc_public'] = rc_public request.run_hook('access.cl.tpldef.register', tpldef, request) return tpldef
def create_record(request): loc = get_localizer(request) cfg = request.registry.settings sess = DBSession() csrf = request.POST.get('csrf', '') if csrf != request.get_csrf(): request.session.flash({ 'text' : loc.translate(_('Error submitting form')), 'class' : 'danger' }) return HTTPSeeOther(location=request.route_url('pdns.cl.domains')) else: #get fields related to obtained type and create corresponding fields rectype = request.POST.get('type', None) if rectype != "record" and rectype != "newdomain": #so we are creating some service, domain, mailserver, etc currentvalues = {} hostname = request.POST.get('hostName', None) currentvalues['name'] = hostname #check if we already have such domain name, #if so, return a warning111 #domain_clash = sess.query(func.count('*'))\ # .select_from(PDNSDomain)\ # .filter(PDNSDomain.name == hostname)\ # .scalar() #if domain_clash > 0: # request.session.flash({ # 'text' : loc.translate(_('Domain already exists, please add corresponding records manually')), # 'class' : 'danger' # }) # return HTTPSeeOther(location=request.route_url('pdns.cl.domains')) #if no same domain name warinigs returned, we can continue processing our data #host record #domaintype = request.POST.get('hosttype', 'NATIVE') domainip = request.POST.get('hostValue', None) #if IP-address is not specified, raise a warning if not domainip: request.session.flash({ 'text' : loc.translate(_('You need to specify IP address')), 'class' : 'danger' }) return HTTPSeeOther(location=request.route_url('pdns.cl.domains')) currentvalues['domainip'] = domainip #get the nameservers from the config ns1 = cfg.get('netprofile.client.pdns.ns1') ns2 = cfg.get('netprofile.client.pdns.ns2') currentvalues['nameserver1'] = ns1 currentvalues['nameserver2'] = ns2 currentvalues['ttl'] = 3600 currentvalues['prefix'] = '' currentvalues['name'] = hostname #and here we create our something. #as we have new service type, rectype, we can get all related fields newdomain = sess.query(PDNSDomain).filter(PDNSDomain.name==hostname).first() service_template = sess.query(PDNSTemplateType).filter(PDNSTemplateType.name==rectype).join(PDNSTemplate).all() #default values are stored as JSON in the database #if default value is a key of a dictionnary, lookup it's value in the currentvalues dict #else it is a complex value with prefix and value from currentvalues dict, as in jabber contents field #some examples: #Domain NS Record: {"ttl":"86400", "content":"nameserver2"} #Mailserver CNAME Record: {"ttl":"3600", "prefix":"mail", "content":"name"} #Jabber SRV Record: {"ttl":"3600", "prefix":"_xmpp-client._tcp", "content":["5 0 5222 jabber", "name"]} for t in service_template: for f in t.template_fields: defvalues = json.loads(f.defaultvalues) newname = currentvalues['name'] if 'prefix' in defvalues.keys(): newname = "{0}.{1}".format(defvalues['prefix'], newname) newrtype = f.field.name defcontent = defvalues.get('content', None) if defcontent: if not isinstance(defcontent, list): newcontent = currentvalues.get(defcontent, None) else: def_in_cur = [defcontent.index(k) for k in filter(lambda x: x in defcontent, currentvalues.keys())] for i in def_in_cur: defcontent[i] = currentvalues[defcontent[i]] newcontent =".".join(defcontent) else: newcontent = '' newttl = int(defvalues.get('ttl', 3600)) newRecord = PDNSRecord( domain = newdomain, name = newname, rtype = newrtype, content = newcontent, ttl = newttl, ) sess.add(newRecord) sess.flush() elif rectype == "record": ttl = None if request.POST.get('ttl', None) == '' else request.POST.get('ttl', None); prio = None if request.POST.get('prio', None) == '' else request.POST.get('prio', None); newrecord = PDNSRecord(domain_id=int(request.POST.get('domainid', None)), name=request.POST.get('name', None), rtype=request.POST.get('rtype', None), content=request.POST.get('content', None), ttl=ttl, prio=prio) sess.add(newrecord) sess.flush() elif rectype == "newdomain": hostname = request.POST.get('hostName', '127.0.0.1') hosttype = request.POST.get('hostType', 'NATIVE') domain_clash = sess.query(func.count('*'))\ .select_from(PDNSDomain)\ .filter(PDNSDomain.name == hostname)\ .scalar() if domain_clash > 0: request.session.flash({ 'text' : loc.translate(_('Domain already exists, please add corresponding records manually')), 'class' : 'danger' }) return HTTPSeeOther(location=request.route_url('pdns.cl.domains')) newdomain = PDNSDomain( name=hostname, master='', dtype=hosttype, account=request.POST.get('user', None) ) sess.add(newdomain) sess.flush() return HTTPSeeOther(location=request.route_url('pdns.cl.domains', _query=(('created', 1),)))
def client_register(request): if authenticated_userid(request): return HTTPSeeOther(location=request.route_url('access.cl.home')) cur_locale = locale_neg(request) loc = get_localizer(request) cfg = request.registry.settings comb_js = asbool(cfg.get('netprofile.client.combine_js', False)) can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False)) must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True)) must_recaptcha = asbool(cfg.get('netprofile.client.registration.recaptcha.enabled', False)) min_pwd_len = int(cfg.get('netprofile.client.registration.min_password_length', 8)) rate_id = int(cfg.get('netprofile.client.registration.rate_id', 1)) state_id = int(cfg.get('netprofile.client.registration.state_id', 1)) maillogin = asbool(cfg.get('netprofile.client.email_as_username', False)) csrf = request.POST.get('csrf', '') errors = {} if not can_reg: return HTTPSeeOther(location=request.route_url('access.cl.login')) if must_recaptcha: rc_private = cfg.get('netprofile.client.recaptcha.private_key') rc_public = cfg.get('netprofile.client.recaptcha.public_key') if (not rc_private) or (not rc_public): # TODO: log missing reCAPTCHA keys must_recaptcha = False if 'submit' in request.POST: sess = DBSession() if csrf != request.get_csrf(): errors['csrf'] = _('Error submitting form') elif must_recaptcha: try: rcresp = verify_recaptcha(rc_private, request) except ValueError as e: errors['recaptcha'] = str(e) else: if rcresp and not rcresp.valid: errors['recaptcha'] = rcresp.text() if len(errors) == 0: login = request.POST.get('user', '') passwd = request.POST.get('pass', '') passwd2 = request.POST.get('pass2', '') email = request.POST.get('email', '') name_family = request.POST.get('name_family', '') name_given = request.POST.get('name_given', '') name_middle = request.POST.get('name_middle', '') l = len(login) if (l == 0) or (l > 254): errors['user'] = _('Invalid field length') elif not maillogin and not _re_login.match(login): errors['user'] = _('Invalid character used in username') l = len(passwd) if l < min_pwd_len: errors['pass'] = _('Password is too short') elif l > 254: errors['pass'] = _('Password is too long') if passwd != passwd2: errors['pass2'] = _('Passwords do not match') l = len(email) if (l == 0) or (l > 254): errors['email'] = _('Invalid field length') elif not _re_email.match(email): errors['email'] = _('Invalid e-mail format') if maillogin: login = email l = len(name_family) if (l == 0) or (l > 254): errors['name_family'] = _('Invalid field length') l = len(name_given) if (l == 0) or (l > 254): errors['name_given'] = _('Invalid field length') l = len(name_middle) if l > 254: errors['name_middle'] = _('Invalid field length') if 'user' not in errors: # XXX: currently we check across all entity types. login_clash = sess.query(func.count('*'))\ .select_from(Entity)\ .filter(Entity.nick == login)\ .scalar() if login_clash > 0: errors['user'] = _('This username is already taken') if len(errors) == 0: ent = PhysicalEntity() ent.nick = login ent.email = email ent.name_family = name_family ent.name_given = name_given if name_middle: ent.name_middle = name_middle ent.state_id = state_id stash = Stash() stash.entity = ent stash.name = loc.translate(_('Primary Account')) acc = AccessEntity() acc.nick = login acc.password = passwd acc.stash = stash acc.rate_id = rate_id acc.state_id = state_id ent.children.append(acc) sess.add(ent) sess.add(stash) sess.add(acc) if must_verify: link_id = int(cfg.get('netprofile.client.registration.link_id', 1)) rand_len = int(cfg.get('netprofile.client.registration.code_length', 20)) queue_mail = asbool(cfg.get('netprofile.client.registration.mail_queue', False)) sender = cfg.get('netprofile.client.registration.mail_sender') acc.access_state = AccessState.block_inactive.value link = AccessEntityLink() link.entity = acc link.type_id = link_id chars = string.ascii_uppercase + string.digits try: rng = random.SystemRandom() except NotImplementedError: rng = random link.value = ''.join(rng.choice(chars) for i in range(rand_len)) link.timestamp = datetime.datetime.now() sess.add(link) mailer = get_mailer(request) tpldef = { 'cur_loc' : cur_locale, 'entity' : ent, 'stash' : stash, 'access' : acc, 'link' : link } request.run_hook('access.cl.tpldef.register.mail', tpldef, request) msg_text = Attachment( data=render('netprofile_access:templates/email_register_plain.mak', tpldef, request), content_type='text/plain; charset=\'utf-8\'', disposition='inline', transfer_encoding='quoted-printable' ) msg_html = Attachment( data=render('netprofile_access:templates/email_register_html.mak', tpldef, request), content_type='text/html; charset=\'utf-8\'', disposition='inline', transfer_encoding='quoted-printable' ) msg = Message( subject=(loc.translate(_('Activation required for user %s')) % login), sender=sender, recipients=(email,), body=msg_text, html=msg_html ) if queue_mail: mailer.send_to_queue(msg) else: mailer.send(msg) return HTTPSeeOther(location=request.route_url('access.cl.regsent')) tpldef = { 'cur_loc' : cur_locale, 'comb_js' : comb_js, 'must_verify' : must_verify, 'must_recaptcha' : must_recaptcha, 'min_pwd_len' : min_pwd_len, 'maillogin' : maillogin, 'errors' : {err: loc.translate(errors[err]) for err in errors} } if must_recaptcha: tpldef['rc_public'] = rc_public request.run_hook('access.cl.tpldef.register', tpldef, request) return tpldef