def view_items(self, request): items = Struct() items.settings = self.settings, items.method = request.method items.formatter = None items.key = '' items.is_rest = self.is_rest items.use_session = self.use_session parameters = dict(request.GET) post_params = dict(request.POST) for k, v in post_params.items(): if k in parameters: parameters[k].append(v) else: parameters[k] = v items.parameters = parameters path = request.path.strip().split('/') if path[0] == '': del path[0] length = len(path) if length > 0 and path[length - 1] == '': del path[length - 1] length = len(path) if length < self.base_path_length: items.error = Result.error(BasicView.CODE_NOT_FOUND, 'Not Found', '01') return items all_path = list(path) base_path = list(path[0:self.base_path_length]) del path[0:self.base_path_length] items.all_path = all_path items.base_path = base_path items.path = path if self.is_rest: lenpath = len(path) if lenpath == 0: items.error = Result.error(BasicView.CODE_NOT_FOUND, 'Not Found', '02') return items lstr = path[lenpath - 1] lidx = lstr.rfind('.') fmt = '' if lidx != -1: fmt = lstr[lidx + 1:].strip() if fmt != '' and fmt in self.formatter: lstr = lstr[:lidx] path[lenpath - 1] = lstr else: fmt = '' if fmt == '' and BasicView.HEADER_RESPONSE_FORMAT in request.META: fmt = request.META[BasicView.HEADER_RESPONSE_FORMAT].strip() items.formatter = self.formatter[fmt] if BasicView.HEADER_ACCESS_KEY in request.META: items.key = request.META[BasicView.HEADER_ACCESS_KEY] else: items.template = self.template return items
def profile(request): view_items = request.view_items formatter = view_items.formatter if view_items.is_rest and not view_items.use_session: key = view_items.key access = BasicView.get_access(formatter, key) if isinstance(access, HttpResponse): return access if access.user is not None and hasattr(access.user, 'password'): del access.user.password if hasattr(access, 'secret'): del access.secret data = Result.success(access) return BasicView.quick_return(formatter=formatter, data=data, nullable=False) else: data = Result.error(BasicView.CODE_NOT_ALLOWED, 'NOT ALLOWED') return BasicView.quick_return(formatter=formatter, data=data, nullable=False)
def logout(request): view_items = request.view_items # rest if view_items.is_rest: formatter = view_items.formatter if view_items.use_session: auth_logout(request) data = Result.success() return BasicView.quick_return(formatter=formatter, data=data, nullable=False) else: key = view_items.key Access.revoke(key) data = Result.success() return BasicView.quick_return(formatter=formatter, data=data, nullable=False) # web else: settings = view_items.settings[0] auth_logout(request) return HttpResponseRedirect(settings['path']['home'])
def get_access(formatter, key, request=None): if key is None or '' == key: data = Result.error(BasicView.CODE_ACCESS_KEY_REQUIRED, 'Access Key is required') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) access = Access.get(key) if access is None: data = Result.error(BasicView.CODE_ACCESS_KEY_EXPIRED, 'Access Key is expired') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) if request is not None and access.secret is not None: secret = BasicView.create_secret(request) if secret != access.secret: data = Result.error(BasicView.CODE_ACCESS_KEY_INVALID, 'Access Key is not valid') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) return access
def login(request): view_items = request.view_items # rest if view_items.is_rest: formatter = view_items.formatter if view_items.use_session and request.user.is_authenticated: data = Result.success("LOGGED_IN") return BasicView.quick_return(formatter=formatter, data=data, nullable=False) parameters = view_items.parameters username = '' if 'username' in parameters: username = parameters['username'][0] password = '' if 'password' in parameters: password = parameters['password'][0] if username == '' or password == '': data = Result.error(BasicView.CODE_USER_PASS_REQUIRED, 'username and password are required') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) authUser = BasicDao.get({'model': AuthUser, 'filter': {'username': username}}) if authUser is None: data = Result.error(BasicView.CODE_USER_NOT_FOUND, 'User is not found') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) if not authUser.is_active: data = Result.error(BasicView.CODE_USER_INACTIVE, 'User is not active') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) pwd_valid = check_password(password, authUser.password) if not pwd_valid: data = Result.error(BasicView.CODE_INVALID_PASSWORD, 'Invalid password') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) authUser.last_login = datetime.now() authUser.save() if view_items.use_session: auth_login(request, authUser) data = Result.success() return BasicView.quick_return(formatter=formatter, data=data, nullable=False) else: key = str(uuid.uuid1()) user = AccessUser(user=authUser) secret = BasicView.create_secret(request) access = Access(user=user, key=key, secret=secret) saved = Access.create(key, access) if not saved: data = Result.error(BasicView.CODE_ACCESS_KEY_REG_FAIL, 'Failed to register Access Key') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) del access.user.password del access.secret data = Result.success(access) return BasicView.quick_return(formatter=formatter, data=data, nullable=False) # web else: settings = view_items.settings[0] redirect_to = '' if REDIRECT_FIELD_NAME in view_items.parameters: redirect_to = view_items.parameters[REDIRECT_FIELD_NAME][0] if request.user.is_authenticated: if not '' == redirect_to: redirect_to = base64.urlsafe_b64decode(redirect_to).decode() if redirect_to == settings['path']['login'] or redirect_to == '': return HttpResponseRedirect(settings['path']['home']) return HttpResponseRedirect(redirect_to) if 'POST' == request.method: form = AuthenticationForm(request, data=request.POST) if form.is_valid(): auth_login(request, form.get_user()) return HttpResponseRedirect(settings['path']['login'] + '?' + REDIRECT_FIELD_NAME + '=' + redirect_to) else: form = AuthenticationForm(request) current_site = get_current_site(request) context = { 'form': form, REDIRECT_FIELD_NAME: redirect_to, 'site': current_site, 'settings': settings, 'request': request } template = view_items.template.login return BasicView.quick_return(template=template, context=context, is_rest=False)
def wrapper(request, *args, **kwargs): view_items = request.view_items formatter = view_items.formatter use_session = view_items.use_session is_rest = view_items.is_rest if 'method' in input and isinstance(input['method'], list): method = request.method if not method.upper() in [ x.upper() for x in input['method'] ]: if is_rest: data = Result.error( BasicView.CODE_UNSUPPORTED_METHOD, 'Method Not Allowed') return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=is_rest) else: context = { 'settings': view_items.settings[0], 'request': request, 'error': { 'status': 405, 'text': 'Method Not Allowed' } } template = view_items.template.status return BasicView.quick_return(template=template, context=context, is_rest=is_rest) if 'private' in input and isinstance(input['private'], bool): private = input['private'] if private: if view_items.is_rest: if use_session: if not request.user.is_authenticated: data = Result.error( BasicView.CODE_USER_NOT_LOGGED_IN, 'User is not logged in') return BasicView.quick_return( formatter=formatter, data=data, nullable=False) else: key = view_items.key access = BasicView.get_access( formatter, key, request) if isinstance(access, HttpResponse): return access view_items.access = access else: if not request.user.is_authenticated: qstring = request.GET.urlencode() redirect = request.path if qstring != '': redirect = redirect + '?' + qstring redirect = base64.urlsafe_b64encode( redirect.encode()).decode() login = view_items.settings[0]['path']['login'] return HttpResponseRedirect( login + '?' + REDIRECT_FIELD_NAME + '=' + redirect) return function(request, *args, **kwargs)
def model(self, request): self.is_rest = True view_items = self.view_items(request) if hasattr(view_items, 'error'): error = view_items.error info = error.info error = error.error data = error['code'] + ' - ' + error['text'] + ' (' + info + ')' return BasicView.quick_return(status=400, data=data, nullable=False, is_rest=self.is_rest) formatter = view_items.formatter path = view_items.path parameters = view_items.parameters if len(path) < 2: data = Result.error(BasicView.CODE_NOT_FOUND, 'Invalid path') return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=self.is_rest) # Model model = self.get_model(path[0]) if model is None: data = Result.error(BasicView.CODE_UNKNOWN_MODEL, 'Unknown model: ' + path[0]) return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=self.is_rest) del path[0] # Action action = path[0] del path[0] if not hasattr(BasicApi, action): data = Result.error(BasicView.CODE_INVALID_ACTION, 'Invalid action: ' + path[0]) return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=self.is_rest) # User user = None if self.use_session: user = get_user(request) if not request.user.is_authenticated and API_USER_ENABLE: data = Result.error(BasicView.CODE_USER_NOT_LOGGED_IN, 'User is not logged in') return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=self.is_rest) else: key = view_items.key if key is None or '' == key: if API_USER_ENABLE: data = Result.error(BasicView.CODE_ACCESS_KEY_REQUIRED, 'Access Key is required') return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=self.is_rest) else: access = Access.get(key) if access is None: if API_USER_ENABLE: data = Result.error(BasicView.CODE_ACCESS_KEY_EXPIRED, 'Access Key is expired') return BasicView.quick_return(formatter=formatter, data=data, nullable=False, is_rest=self.is_rest) else: if access.secret is not None and API_USER_ENABLE: secret = BasicView.create_secret(request) if secret != access.secret: data = Result.error( BasicView.CODE_ACCESS_KEY_INVALID, 'Access Key is not valid') return BasicView.quick_return(formatter=formatter, data=data, nullable=False) user = access.user if ACCESS_TOUCH_ENABLE: Access.touch(key) # Execute command = getattr(BasicApi, action) status = 200 try: data = command({ 'model': model, 'path': path, 'parameters': parameters, 'user': user }) result = Result.success(data) except BasicApi.NotAllowed: result = Result.error(BasicView.CODE_NOT_ALLOWED, 'Not allowed') except BasicApi.BadRequest as br: result = Result.error(BasicView.CODE_BAD_REQUEST, str(br)) except BasicApi.AppError as ar: logger.error(ar) result = Result.error(BasicView.CODE_APP_SYS_ERROR, 'AppError: ' + str(ar)) status = 500 except Exception as ex: logger.error(ex) result = Result.error(BasicView.CODE_APP_SYS_ERROR, 'SysError: ' + str(ex)) status = 500 mapi = BasicApi.get_model_api(model) kwargs = {} if hasattr(mapi, 'alias'): kwargs['alias'] = getattr(mapi, 'alias') if hasattr(mapi, 'ignore'): ignore = getattr(mapi, 'ignore') if ignore is not None and 'output' in ignore: kwargs['hidden'] = ignore['output'] if hasattr(mapi, 'nullable'): kwargs['nullable'] = getattr(mapi, 'nullable') return HttpResponse(formatter.content_data(result, **kwargs), formatter.content_type(), status)
def route(self, request): view_items = self.view_items(request) ctx = Struct({ 'is_rest': self.is_rest, 'formatter': view_items.formatter, 'data': None, 'status': 200, 'nullable': False, 'template': None, 'context': { 'settings': self.settings, 'request': request }, }) if hasattr(view_items, 'error'): error = view_items.error info = error.info error = error.error ctx.context.text = info ctx.data = error['code'] + ' - ' + error['text'] + ' (' + info + ')' ctx.status = 400 ctx.template = self.template.notfound else: ctx.template = self.template.home path = list(view_items.path) del view_items.path lenpath = len(path) if lenpath > 0: package_object = None view_items.package_path = [] for x in range(0, 3): i = 3 - x if lenpath < i: continue p = '/'.join(s for s in path[0:i]) if p in self.route_packages: package_object = self.route_packages[p] view_items.package_path = list(path[0:i]) del path[0:i] break lenpath = len(path) if package_object is None: ctx.context.text = '03' ctx.data = Result.error(BasicView.CODE_NOT_FOUND, 'Not Found (03)') ctx.template = self.template.notfound elif lenpath == 0: ctx.context.text = '04' ctx.data = Result.error(BasicView.CODE_NOT_FOUND, 'Not Found (04)') ctx.template = self.template.notfound else: if not hasattr(package_object, path[0]): ctx.context.text = '05' ctx.data = Result.error(BasicView.CODE_NOT_FOUND, 'Not Found (05)') ctx.template = self.template.notfound else: module_object = getattr(package_object, path[0]) view_items.module_path = [path[0]] del path[0] lenpath = len(path) module_idx = -1 for i in range(0, lenpath): if not hasattr(module_object, path[i]): break module_object = getattr(module_object, path[i]) view_items.module_path.append(path[i]) module_idx = i if module_idx != -1: del path[0:module_idx + 1] view_items.function_path = list(path) if not callable(module_object): ctx.context.text = '06' ctx.data = Result.error(BasicView.CODE_NOT_FOUND, 'Not Found (06)') ctx.template = self.template.notfound else: request.view_items = view_items try: is_function = str(type( module_object)) == '<class \'function\'>' if is_function: result = module_object(request) else: function_object = module_object( settings=self.settings) result = function_object.call(request) # Default nullable = True, agar false maka di view_items harus diset ctx.nullable = True if hasattr(request.view_items, 'nullable') and isinstance( request.view_items.nullable, bool): ctx.nullable = request.view_items.nullable if isinstance(result, HttpResponse): return result elif isinstance(result, ViewResponse): ctx.context.context = result.context ctx.data = result.context ctx.template = result.template else: ctx.context.context = result ctx.data = result ctx.template = request.view_items.template except Exception as ex: logger.error(ex) ctx.context.error = { 'code': '99', 'text': str(ex) } ctx.data = Result.error( BasicView.CODE_APP_SYS_ERROR, str(ex)) ctx.nullable = False ctx.template = self.template.error try: if not self.is_rest: for key, func in self.context_interceptors.items(): if hasattr(ctx.context, key): continue value = func(request) setattr(ctx.context, key, value) kwargs = ctx.__dict__ return BasicView.quick_return(**kwargs) except Exception as ex: logger.error(ex) ctx.context.error = {'code': '99', 'text': str(ex)} ctx.template = self.template.error return BasicView.quick_return(**kwargs)
def coba3(request): request.view_items.template = 'test.html' return Result.error('22', 'Tes salah method')
def coba2(request): request.view_items.template = 'test.html' return Result.error('21', 'Test Error')