class ReferencedListFieldNonFullTestResource(resources.MongoEngineResource): referencedlist = fields.ReferencedListField(of='test_project.test_app.api.resources.PersonResource', attribute='referencedlist', full=False, null=True) class Meta: queryset = documents.ReferencedListFieldTest.objects.all() allowed_methods = ('get', 'post', 'put', 'patch', 'delete') authorization = tastypie_authorization.Authorization()
class LotteryResource(BaseResource): users = fields.ReferencedListField(of='apis.base.resources.UserResource', attribute='users', full=True, null=True) paper = fields.ReferenceField(to='apis.base.resources.PaperResource', attribute='paper', full=True, null=True) class Meta: queryset = Lottery.objects(is_online=True) allowed_methods = ('get', ) authentication = UserAuthentication() authorization = Authorization() filtering = {'period': ALL} def prepend_urls(self): return [ url(r"^(?P<resource_name>%s)/yesterday%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('yesterday'), name="api_yesterday"), ] def yesterday(self, request, **kwargs): today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) yesterday = today - timedelta(days=1) params = dict(request.GET.dict().items() + { 'period__gte': yesterday, 'period__lt': today }.items()) return redirect(u'{}/api/v1/lottery/?{}'.format( SUB_DOMAIN or '', urlencode(params)))
class InvoiceBaseGroupResource(TenantResource): quotation = fields.ReferenceField( to='invoicing.api.resources.QuotationResource', attribute='quotation', readonly=True, null=True, help_text=HELP_TEXT['invoice_base_group']['quotation']) purchase_order = fields.ReferenceField( to='invoicing.api.resources.PurchaseOrderResource', attribute='purchase_order', readonly=True, null=True, help_text=HELP_TEXT['invoice_base_group']['purchase_order']) down_payment_invoices = fields.ReferencedListField( of='invoicing.api.resources.DownPaymentInvoiceResource', attribute='down_payment_invoices', readonly=True, null=True, help_text=HELP_TEXT['invoice_base_group']['down_payment_invoices']) invoice = fields.ReferenceField( to='invoicing.api.resources.InvoiceResource', attribute='invoice', readonly=True, null=True, help_text=HELP_TEXT['invoice_base_group']['invoice']) invoices_cancelled = fields.ReferencedListField( of='invoicing.api.resources.InvoiceResource', attribute='invoices_cancelled', readonly=True, null=True, help_text=HELP_TEXT['invoice_base_group']['invoices_cancelled']) credit_notes = fields.ReferencedListField( of='invoicing.api.resources.CreditNoteResource', attribute='credit_notes', readonly=True, null=True, help_text=HELP_TEXT['invoice_base_group']['credit_notes']) class Meta(TenantResource.Meta): resource_name = 'invoice_base_group' object_class = InvoiceBaseGroup list_allowed_methods = ('get', ) detail_allowed_methods = ('get', ) excludes = ('tenant', )
class ContactGroupResource(resources.MongoEngineResource): contacts = fields.ReferencedListField( of='test_project.test_app.api.resources.ContactResource', attribute='contacts', null=True) class Meta(object): queryset = documents.ContactGroup.objects.all() allowed_methods = ('get', 'post', 'put', 'patch', 'delete') authorization = tastypie_authorization.Authorization()
class PackageResource(resources.MongoEngineResource): functions = fields.ReferencedListField( of='netlambda.resources.FunctionResource', attribute='functions', full=True, null=True) class Meta: object_class = models.Package allowed_methods = ('get') resource_name = 'pack'
class WorkspaceResource(mongoresources.MongoEngineResource): user = fields.ReferenceField(to='lisa.server.web.weblisa.api.UserResource', attribute='user') widgets = fields.ReferencedListField( of='lisa.server.web.interface.api.WidgetByUserResource', attribute='widgets', full=True, null=True, help_text='List of widgets') class Meta: queryset = Workspace.objects.all() allowed_methods = ('get', 'post', 'put', 'patch') authorization = authorization.Authorization()
class QuizResource(BaseResource): products = fields.ReferencedListField( of='apis.base.resources.ProductResource', attribute='products', full=True, null=True) class Meta: queryset = Quiz.objects() allowed_methods = ('get', ) authentication = UserAuthentication() authorization = Authorization() excludes = ('resource_uri', ) ordering = ('created_at', )
class InvoiceResource(InvoiceBaseResource): state = base_fields.CharField( attribute='state', readonly=True, help_text=HELP_TEXT['invoice']['state'] ) paid = base_fields.DecimalField( attribute='paid', readonly=True, help_text=HELP_TEXT['invoice']['paid'] ) balance = base_fields.DecimalField( attribute='balance', readonly=True, help_text=HELP_TEXT['invoice']['balance'] ) has_temporary_reference = base_fields.BooleanField( attribute='has_temporary_reference', readonly=True, help_text=HELP_TEXT['invoice']['has_temporary_reference'] ) related_to = fields.ReferenceField( to='invoicing.api.resources.QuotationResource', attribute='related_to', readonly=True, null=True, help_text=HELP_TEXT['invoice']['related_to'] ) payments = fields.ReferencedListField( of='invoicing.api.resources.PaymentResource', attribute='payments', readonly=True, null=True, blank=True, help_text=HELP_TEXT['invoice']['payments'] ) class Meta(InvoiceBaseResource.Meta): queryset = Invoice.objects.all() detail_specific_methods = ('cancel', 'mark_as_registered') def prepend_urls(self): """Add urls for resources actions.""" urls = super(InvoiceResource, self).prepend_urls() urls.extend(( url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/cancel%s$' % (self._meta.resource_name, trailing_slash()), self.wrap_view('invoice_cancel'), name='api_invoice_cancel'), )) return urls def invoice_cancel(self, request, **kwargs): """Cancel the invoice and returns the associated credit note.""" from invoicing.api.resources.credit_note import CreditNoteResource self.method_check(request, allowed=['put']) self.is_authenticated(request) self.throttle_check(request) try: bundle = self.build_bundle(request=request) obj = self.cached_obj_get(bundle=bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() try: credit_note = obj.cancel(request.vosae_user) invoicing_signals.post_cancel_invoice.send(obj.__class__, issuer=request.vosae_user, document=obj, credit_note=credit_note) credit_note_resource = CreditNoteResource() credit_note_resource_bundle = credit_note_resource.build_bundle(obj=credit_note, request=request) except NotCancelableInvoice as e: raise BadRequest(e) self.log_throttled_access(request) to_be_serialized = { 'credit_note_uri': credit_note_resource.get_resource_uri(credit_note_resource_bundle) } to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized) return self.create_response(request, to_be_serialized) def dehydrate_related_to(self, bundle): from invoicing.api.resources import QuotationResource, PurchaseOrderResource try: if bundle.obj.related_to.is_quotation(): resource = QuotationResource() elif bundle.obj.related_to.is_purchase_order(): resource = PurchaseOrderResource() resource_bundle = resource.build_bundle(obj=bundle.obj.related_to, request=bundle.request) return resource.get_resource_uri(resource_bundle) except: return
class InvoiceBaseResource(NotificationAwareResourceMixin, TenantResource, VosaeIMEXMixinResource): reference = base_fields.CharField( attribute='reference', readonly=True, help_text=HELP_TEXT['invoicebase']['reference']) total = base_fields.DecimalField( attribute='total', readonly=True, help_text=HELP_TEXT['invoicebase']['total']) amount = base_fields.DecimalField( attribute='amount', readonly=True, help_text=HELP_TEXT['invoicebase']['amount']) account_type = base_fields.CharField( attribute='account_type', help_text=HELP_TEXT['invoicebase']['account_type']) issuer = fields.ReferenceField( to='core.api.resources.VosaeUserResource', attribute='issuer', readonly=True, help_text=HELP_TEXT['invoicebase']['issuer']) organization = fields.ReferenceField( to='contacts.api.resources.OrganizationResource', attribute='organization', readonly=True, null=True, help_text=HELP_TEXT['invoicebase']['organization']) contact = fields.ReferenceField( to='contacts.api.resources.ContactResource', attribute='contact', readonly=True, null=True, help_text=HELP_TEXT['invoicebase']['contact']) history = fields.EmbeddedListField( of='invoicing.api.resources.InvoiceHistoryEntryResource', attribute='history', readonly=True, full=True, null=True, blank=True, help_text=HELP_TEXT['invoicebase']['history']) notes = fields.EmbeddedListField( of='invoicing.api.resources.InvoiceNoteResource', attribute='notes', full=True, null=True, blank=True, help_text=HELP_TEXT['invoicebase']['notes']) group = fields.ReferenceField( to='invoicing.api.resources.InvoiceBaseGroupResource', attribute='group', readonly=True, help_text=HELP_TEXT['invoicebase']['group']) attachments = fields.ReferencedListField( of='core.api.resources.VosaeFileResource', attribute='attachments', null=True, blank=True, help_text=HELP_TEXT['invoicebase']['attachments']) class Meta(TenantResource.Meta): excludes = ('tenant', 'base_type', 'subscribers') filtering = { 'state': ('exact', 'in'), 'contact': ('exact', ), 'organization': ('exact', ), 'account_type': ('exact', ), 'reference': ('contains', ) } available_imex_serializers = (invoicing_imex.PDFSerializer, ) def prepend_urls(self): """Add urls for resources actions.""" urls = super(InvoiceBaseResource, self).prepend_urls() urls.extend(VosaeIMEXMixinResource.prepend_urls(self)) urls.extend(( url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/send/mail%s$' % (self._meta.resource_name, trailing_slash()), self.wrap_view('send_by_mail'), name='api_invoicebase_send_by_mail'), url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/mark_as_(?P<invoicebase_state>(%s))%s$' % (self._meta.resource_name, '|'.join( [k.lower() for k in MARK_AS_STATES]), trailing_slash()), self.wrap_view('mark_as_state'), name='api_invoicebase_mark_as_state'), url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/generate_pdf%s$' % (self._meta.resource_name, trailing_slash()), self.wrap_view('generate_pdf'), name='api_invoicebase_generate_pdf'), )) return urls @classmethod def post_save(self, sender, resource, bundle, created, **kwargs): """ Post save API hook handler - Add timeline and notification entries """ # Add timeline and notification entries invoicebase_saved_task.delay(bundle.request.vosae_user, bundle.obj, created) def obj_delete(self, bundle, **kwargs): """Raises a BadRequest if the :class:`~invoicing.models.InvoiceBase` is not in a deletable state""" try: super(InvoiceBaseResource, self).obj_delete(bundle, **kwargs) except NotDeletableInvoice as e: raise BadRequest(e) def do_export(self, request, serializer, export_objects): """Export""" if len(export_objects) is not 1: raise BadRequest('PDF export can only be done on a single item.') return serializer.serialize(export_objects[0]), None def send_by_mail(self, request, **kwargs): """Send an InvoiceBase by mail.""" self.method_check(request, allowed=['post']) self.is_authenticated(request) self.throttle_check(request) try: bundle = self.build_bundle(request=request) obj = self.cached_obj_get(bundle=bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() try: email_data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) subject = email_data.get('subject') message = email_data.get('message') to = email_data.get('to') cc = email_data.get('cc', []) bcc = email_data.get('bcc', []) assert isinstance(to, list) and isinstance( cc, list) and isinstance(bcc, list) except: raise BadRequest('Invalid email parameters.') try: obj.send_by_mail(subject, message, to, cc, bcc, request.vosae_user) except: raise BadRequest('Can\'t send email. Verify parameters.') self.log_throttled_access(request) to_be_serialized = {} to_be_serialized = self.alter_list_data_to_serialize( request, to_be_serialized) return self.create_response(request, to_be_serialized) def mark_as_state(self, request, invoicebase_state, **kwargs): """Set state for an InvoiceBase.""" self.method_check(request, allowed=['put']) self.is_authenticated(request) self.throttle_check(request) try: bundle = self.build_bundle(request=request) obj = self.cached_obj_get(bundle=bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() try: previous_state, new_state = obj.set_state( invoicebase_state.upper(), issuer=request.vosae_user) invoicing_signals.post_client_changed_invoice_state.send( obj.__class__, issuer=request.vosae_user, document=obj, previous_state=previous_state) except (obj.InvalidState, InvalidInvoiceBaseState) as e: raise BadRequest(e) self.log_throttled_access(request) return http.HttpNoContent() # May need to use this with ember (check if always_return_data) # to_be_serialized = '' # to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized) # return self.create_response(request, to_be_serialized) def generate_pdf(self, request, **kwargs): """Generate a PDF""" self.method_check(request, allowed=['get']) self.is_authenticated(request) self.throttle_check(request) try: bundle = self.build_bundle(request=request) obj = self.cached_obj_get(bundle=bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() try: language = request.META.get('HTTP_X_REPORT_LANGUAGE', None) if language is not None: assert language in [k[0] for k in settings.LANGUAGES] except: raise BadRequest('Invalid language parameters.') try: pdf = obj.get_pdf(issuer=request.vosae_user, language=language) pdf_resource = VosaeFileResource() pdf_resource_bundle = pdf_resource.build_bundle(obj=pdf, request=request) except Exception, e: print e raise BadRequest('Can\'t generate PDF. Verify parameters.') self.log_throttled_access(request) pdf_resource_bundle = pdf_resource.full_dehydrate(pdf_resource_bundle) pdf_resource_bundle = pdf_resource.alter_detail_data_to_serialize( request, pdf_resource_bundle) return pdf_resource.create_response(request, pdf_resource_bundle)
class PaperResource(BaseResource): quizes = fields.ReferencedListField(of='apis.base.resources.QuizResource', attribute='quizes', full=True, null=True) class Meta: queryset = Paper.objects(is_online=True) allowed_methods = ('get', ) authentication = UserAuthentication() authorization = Authorization() excludes = ('resource_uri', ) filtering = {'period': ALL} ordering = ('period', ) def prepend_urls(self): return [ url(r"^(?P<resource_name>%s)/current%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('current'), name="api_current"), url(r"^(?P<resource_name>%s)/history%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('history'), name="api_history"), url(r"^(?P<resource_name>%s)/yesterday%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('yesterday'), name="api_yesterday"), ] def current(self, request, **kwargs): today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) tomorrow = today + timedelta(days=1) params = dict(request.GET.dict().items() + { 'period__gte': today, 'period__lt': tomorrow }.items()) return redirect(u'{}/api/v1/paper/?{}'.format(SUB_DOMAIN or '', urlencode(params))) def yesterday(self, request, **kwargs): today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) yesterday = today - timedelta(days=1) params = dict(request.GET.dict().items() + { 'period__gte': yesterday, 'period__lt': today }.items()) return redirect(u'{}/api/v1/paper/history/?{}'.format( SUB_DOMAIN or '', urlencode(params))) def history(self, request, **kwargs): today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) param_dict = request.GET.dict() params = dict(param_dict.items() + {'period__lt': today}.items()) \ if 'period__lt' not in param_dict or datetime.strptime(param_dict['period__lt'], '%Y-%m-%d %H:%M:%S') > today else param_dict papers_url = u'http://{}/api/v1/paper/?{}'.format( request.META['HTTP_HOST'], urlencode(params)) earliest_paper = Paper.objects().order_by('period').first() earliest = earliest_paper.period if earliest_paper else None if not request.user.is_authenticated(): res = requests.get(papers_url).json() for data in res['objects']: paper_id = data['id'] paper_answers = data.get('answers', {}) paper = Paper.objects(id=paper_id).first() if not paper: continue for quiz in data.get('quizes', []): for prod in quiz.get('products', []): if quiz['id'] in paper_answers \ and prod['id'] in paper_answers[quiz['id']]: prod['score'] = paper_answers[quiz['id']][ prod['id']] if 'answers' in data: del data['answers'] res['meta']['earliest'] = earliest return self.create_response(request, res) else: res = requests.get(papers_url).json() for data in res['objects']: paper_id = data['id'] paper = Paper.objects(id=paper_id).first() if not paper: continue mark = Mark.objects(paper=paper, user=request.user).first() paper_answers = data.get('answers', {}) if mark: mark_answers = mark.answers data['mark'] = {} data['mark']['score'] = mark.score data['mark']['rank'] = mark.rank data['mark']['answers'] = mark_answers data['mark']['bonus'] = mark.bonus for quiz in data.get('quizes', []): for prod in quiz.get('products', []): if quiz['id'] in paper_answers \ and prod['id'] in paper_answers[quiz['id']]: prod['score'] = paper_answers[quiz['id']][ prod['id']] if mark: prod['is_mark'] = (quiz['id'] in mark_answers) \ and (prod['id'] == mark_answers[quiz['id']]) if 'answers' in data: del data['answers'] res['meta']['earliest'] = earliest return self.create_response(request, res)
class UserResource(BaseResource): accounts = fields.ReferencedListField( of='apis.base.resources.AccountResource', attribute='accounts', full=True, null=True) class Meta: queryset = User.objects() allowed_methods = ('get', ) detail_allowed_methods = ('get', 'post') authentication = UserAuthentication() authorization = Authorization() always_return_data = True fields = [ 'id', 'username', 'email', 'screen_name', 'phone', 'device', 'accounts', 'is_active', 'last_login', 'date_joined' ] ordering = ('username', 'last_login', 'date_joined') def prepend_urls(self): return [ url(r"^(?P<resource_name>%s)/login%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('login'), name="api_login"), url(r"^(?P<resource_name>%s)/open_login%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('open_login'), name="api_open_login"), url(r"^(?P<resource_name>%s)/bind%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('bind'), name="api_bind"), url(r"^(?P<resource_name>%s)/logout%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('logout'), name="api_logout"), url(r"^(?P<resource_name>%s)/register%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('register'), name="api_register"), url(r"^(?P<resource_name>%s)/(?P<user_id>\w+)/chgpwd%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('change_password'), name="api_change_password"), url(r"^(?P<resource_name>%s)/fgtpwd%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('forget_password'), name="api_forget_password"), url(r"^(?P<resource_name>%s)/(?P<user_id>\w+)/rstpwd%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('reset_password'), name="api_reset_password"), url(r"^(?P<resource_name>%s)/auth%s$" % (self._meta.resource_name, trailing_slash()), \ self.wrap_view('auth'), name="api_auth"), ] def post_detail(self, request, **kwargs): return self.patch_detail(request, **kwargs) def dehydrate(self, bundle): for k in bundle.data: if k == 'phone' and bundle.data[k] is None: bundle.data[k] = '' return bundle def to_json(self, object_user): data = { field: getattr(object_user, field) for field in self._meta.fields if getattr(object_user, field) } if 'accounts' in data and len(data['accounts']): data['accounts'] = [{ field: getattr(acc, field) for field in acc._fields } for acc in data['accounts']] return data def auth(self, request, **kwargs): """ Just help check if the request is authenticated. """ return self.create_response(request, {'response': request.user}) def validate_password(self, password=''): return (len(password) >= 6 and len(password) <= 20) def bind(self, request, **kwargs): self.method_check(request, allowed=('post', )) u = request.user if not u.is_authenticated(): return self.create_response( request, {'error_message': 'no login user to bind'}, response_class=HttpUnauthorized) data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) aid = data.get('aid') platform = data.get('platform') screen_name = data.get('screen_name') token = data.get('token') bind_type = data.get('bind_type') validation_error = {} for var in ['aid', 'platform', 'screen_name', 'bind_type']: if not locals().get(var): validation_error[var] = 'the param is required.' continue if validation_error: return self.create_response(request, validation_error, HttpBadRequest) Account.objects(aid=aid, platform=platform).update_one( \ set__screen_name=screen_name, set__token=token, upsert=True) account = Account.objects(aid=aid, platform=platform).first() users = User.objects(accounts=account) for user in users: if user.id != u.id: user.accounts.remove(account) user.save() if bind_type == 'add': if account in u.accounts: return self.create_response(request, { 'error_code': 1, 'error_message': 'already binding' }) u.accounts.append(account) u.save() elif bind_type == 'delete': if account not in u.accounts: return self.create_response( request, { 'error_code': 2, 'error_message': 'already unbinding' }) if not u.email and len(u.accounts) == 1: return self.create_response( request, { 'error_code': 3, 'error_message': 'open login user can not unbind the account' }) u.accounts.remove(account) u.save() account.delete() return self.create_response(request, self.to_json(u)) def open_login(self, request, **kwargs): try: self.method_check(request, allowed=('post', )) data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) aid = str(data.get('aid')) platform = data.get('platform') screen_name = data.get('screen_name') token = data.get('token') device_platform = data.get('device_platform') device_id = data.get('device_id') device = u'{}_{}'.format(device_platform, device_id) if not aid or not platform or not screen_name: return self.create_response(request, \ {'error_code': 1, 'error_message': 'aid, platform, screen_name is not correct'}, HttpBadRequest) # old user account = Account.objects(aid=aid, platform=platform).first() if account: user = User.objects(accounts=account).first() if not user: account.delete() return self.create_response(request, \ {'error_code': 2, 'error_message': 'error existing account with no user binded, please retry'}, HttpBadRequest) account.screen_name = screen_name account.token = token account.save() user.backend = AUTHENTICATION_BACKENDS[0] login(request, user) return self.create_response(request, self.to_json(user)) # new user if User.objects(device=device): return self.create_response( request, {'error_message': 'device has been registered'}, HttpForbidden) account = Account( aid=aid, platform=platform, screen_name=screen_name, token=token, ) account.save() new_user = User().create_user( username=str(ObjectId()), password=SECRET_KEY, screen_name=screen_name, device=device, accounts=[account], ) user = authenticate(username=new_user.username, password=SECRET_KEY) login(request, user) return self.create_response(request, self.to_json(user)) except: traceback.print_exc() def login(self, request, **kwargs): self.method_check(request, allowed=('post', )) data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) username = data.get('username') password = data.get('password') user = authenticate(username=username, password=password) if user: login(request, user) return self.create_response(request, self.to_json(user)) else: return self.create_response( request, {'error_message': 'incorrect username or password'}, HttpUnauthorized) def logout(self, request, **kwargs): if request.user and request.user.is_authenticated(): Notification.objects(user=request.user).delete() logout(request) return self.create_response(request, {'success': True}) else: return self.create_response(request, {'error_message': 'no user to logout'}, HttpUnauthorized) def register(self, request, **kwargs): self.method_check(request, allowed=('post', )) data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) password = data.get('password') screen_name = data.get('screen_name') email = data.get('email') username = email phone = data.get('phone') device_platform = data.get('device_platform') device_id = data.get('device_id') device = u'{}_{}'.format(device_platform, device_id) validation_error = {} for var in [ 'password', 'device_id', 'device_platform', 'email', 'screen_name' ]: if not locals().get(var): validation_error[var] = u'the post param is required' continue if validation_error: return self.create_response(request, validation_error, HttpBadRequest) user = User.objects( Q(username=username) | Q(device=device) | Q(email=email) | Q(screen_name=screen_name)).first() if user: if user.username == username: return self.create_response(request, { 'error_code': 1, 'error_message': 'user exists' }) if user.email == email: return self.create_response(request, { 'error_code': 2, 'error_message': 'email exists' }) if user.device == device: return self.create_response( request, { 'error_code': 3, 'error_message': u'device has been registered {}'.format(device) }) if user.screen_name == screen_name: return self.create_response( request, { 'error_code': 4, 'error_message': 'screen_name exists' }) if not self.validate_password(password): return self.create_response(request, { 'error_code': 5, 'error_message': 'password invalid' }) try: new_user = User().create_user( username=username, password=password, email=email, screen_name=screen_name, phone=phone, device=device, ) except ValidationError: return self.create_response( request, { 'error_code': 6, 'error_message': 'email format not correct' }) user = authenticate(username=username, password=password) login(request, user) return self.create_response(request, self.to_json(user)) def change_password(self, request, **kwargs): self.method_check(request, allowed=('post', )) user_id = kwargs.get('user_id') if not request.user.is_authenticated() or request.user.id != user_id: return self.create_response(request, { 'error_code': 1, 'error_message': 'user error' }, HttpUnauthorized) data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) old_password = data.get('old_password') new_password = data.get('new_password') confirm_password = data.get('confirm_password') if old_password == new_password: return self.create_response(request, \ {'error_code': 1, 'error_message': 'old password must be different from new password'}, HttpBadRequest) if new_password != confirm_password: return self.create_response(request, \ {'error_code': 2, 'error_message': 'new password must be equal with confirm password'}, HttpBadRequest) if not self.validate_password(new_password): return self.create_response(request, \ {'error_code': 3, 'error_message': 'new password invalid, should be 6-20 digits'}, HttpBadRequest) u = User.objects(id=user_id).first() user = authenticate(username=u.username, password=old_password) if not user or not user.is_authenticated: return self.create_response(request, { 'error_code': 1, 'error_message': 'old password error' }) u.set_password(new_password) u.save() return self.create_response(request, {'success': True}) def forget_password(self, request, **kwargs): try: self.method_check(request, allowed=('post', )) data = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) user = User.objects(email=data.get('email')).first() if user is None: return self.create_response(request, {'error_message': 'email error'}, HttpBadRequest) token = signing.dumps(user.id, key=SECRET_KEY) PwdRstToken.objects(user=user).update_one( set__token=token, set__generated_at=datetime.utcnow(), set__expires=10, set__validated=False, upsert=True) if DEBUG: link = reverse('api_reset_password', kwargs={ 'resource_name': self._meta.resource_name, 'api_name': 'v1', 'user_id': user.id }) else: link = u'http://{}/{}/api/v1/user/{}/rstpwd/'.format( HOST, APP_NAME, user.id) url = u'{}?token={}&format=json'.format( request.build_absolute_uri(link), token) c = Context({'user': user, 'APP_NAME': APP_NAME, 'url': url}) html_content = loader.get_template('fgtpwd.html').render(c) email = EmailMultiAlternatives(u'验证登录邮箱【{}安全中心 】'.format(APP_NAME), '', EMAIL_HOST_USER, [user.email]) email.attach_alternative(html_content, "text/html") email.send() return self.create_response(request, {'success': True}) except: traceback.print_exc() raise def reset_password(self, request, **kwargs): user_id = kwargs.get('user_id') token = request.GET.get('token') user = User.objects.get(id=user_id) prt = PwdRstToken.objects( user=user, token=token).order_by('-generated_at').first() if request.method == 'GET': if prt is None: return HttpResponse(u'此链接不存在,用户不合法') elif (prt.generated_at + timedelta(minutes=prt.expires)) < datetime.utcnow(): return HttpResponse(u'链接已过期') return render(request, 'rstpwd.html', { 'username': user.username, 'user_id': user.id, 'token': token, }) elif request.method == 'POST': password = request.POST.get('password') confirm_password = request.POST.get('confirm_password') invalid_message = '' if prt is None or \ (prt.generated_at + timedelta(minutes=prt.expires)) < datetime.utcnow(): invalid_message = u'此密码修改已经失效,请重新申请忘记密码' if prt.validated: invalid_message = u'已修改过密码' elif not password or not confirm_password: invalid_message = u'密码不得为空' elif password != confirm_password: invalid_message = u'新密码与确认密码不一致' elif not self.validate_password(password): invalid_message = u'密码应该在6-20 位' if invalid_message: return render( request, 'rstpwd.html', { 'invalid_message': invalid_message, 'username': user.username, 'user_id': user.id, 'token': token, }) else: user.set_password(password) prt.validated = True user.save() prt.save() return HttpResponse('修改成功')
class VosaeUserResource(WakeUpMixinResource, ZombieMixinResource, TenantResource): full_name = base_fields.CharField( attribute='get_full_name', readonly=True, help_text=HELP_TEXT['vosae_user']['full_name']) email = base_fields.CharField(attribute='email', help_text=HELP_TEXT['vosae_user']['email']) status = base_fields.CharField(attribute='status', blank=True, help_text=HELP_TEXT['vosae_user']['status']) photo_uri = base_fields.CharField( attribute='photo_uri', readonly=True, null=True, blank=True, help_text=HELP_TEXT['vosae_user']['photo_uri']) specific_permissions = base_fields.DictField( attribute='specific_permissions', blank=True, help_text=HELP_TEXT['vosae_user']['specific_permissions']) permissions = base_fields.ListField( readonly=True, help_text=HELP_TEXT['vosae_user']['permissions']) groups = fields.ReferencedListField( of='core.api.resources.VosaeGroupResource', attribute='groups', null=True, blank=True, help_text=HELP_TEXT['vosae_user']['groups']) settings = fields.EmbeddedDocumentField( embedded='core.api.resources.VosaeUserSettingsResource', attribute='settings', help_text=HELP_TEXT['vosae_user']['settings']) class Meta(TenantResource.Meta): resource_name = 'user' queryset = VosaeUser.objects.all() list_allowed_methods = ('get', 'post') excludes = ('tenant', ) filtering = {"email": ('exact', )} @classmethod def post_create(self, sender, resource, bundle, **kwargs): """ Post create hook. Fills initial data (based on request's language) after VosaeUser creation """ # Fill user initial data (Tenant and VosaeUser are required) fill_user_initial_data.delay(bundle.obj, bundle.request.LANGUAGE_CODE) def hydrate_email(self, bundle): """ Email can only be used on POST (creation) in order to link the :class:`~core.models.VosaeUser` to the Django user. """ if bundle.request.method.lower() != 'post': bundle.data.update(email=bundle.obj.email) return bundle def dehydrate_permissions(self, bundle): """Returns the list of acquired permissions""" return list(bundle.obj.permissions.acquired)