From 26d1fd50f8303a2e1e710475e964284bf2b673c3 Mon Sep 17 00:00:00 2001 From: irfanpule Date: Wed, 7 Feb 2018 06:42:02 +0700 Subject: [PATCH] initial --- academy/__init__.py | 0 academy/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 143 bytes academy/__pycache__/settings.cpython-36.pyc | Bin 0 -> 2672 bytes academy/__pycache__/urls.cpython-36.pyc | Bin 0 -> 933 bytes academy/__pycache__/wsgi.cpython-36.pyc | Bin 0 -> 547 bytes academy/apps/__init__.py | 0 .../apps/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 148 bytes academy/apps/accounts/__init__.py | 0 .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 157 bytes .../accounts/__pycache__/admin.cpython-36.pyc | Bin 0 -> 1145 bytes .../__pycache__/models.cpython-36.pyc | Bin 0 -> 2382 bytes academy/apps/accounts/admin.py | 26 ++++ academy/apps/accounts/apps.py | 8 + .../apps/accounts/migrations/0001_initial.py | 63 ++++++++ academy/apps/accounts/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-36.pyc | Bin 0 -> 3270 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 168 bytes academy/apps/accounts/models.py | 55 +++++++ academy/apps/accounts/views.py | 6 + academy/core/__init__.py | 0 .../core/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 148 bytes .../__pycache__/custom_auth.cpython-36.pyc | Bin 0 -> 1003 bytes academy/core/__pycache__/utils.cpython-36.pyc | Bin 0 -> 307 bytes .../__pycache__/validators.cpython-36.pyc | Bin 0 -> 2360 bytes academy/core/custom_auth.py | 26 ++++ academy/core/utils.py | 3 + academy/core/validators.py | 69 +++++++++ academy/settings.py | 137 ++++++++++++++++++ academy/urls.py | 21 +++ academy/wsgi.py | 16 ++ db.sqlite3 | Bin 0 -> 143360 bytes manage.py | 22 +++ requirements.txt | 7 + 33 files changed, 459 insertions(+) create mode 100644 academy/__init__.py create mode 100644 academy/__pycache__/__init__.cpython-36.pyc create mode 100644 academy/__pycache__/settings.cpython-36.pyc create mode 100644 academy/__pycache__/urls.cpython-36.pyc create mode 100644 academy/__pycache__/wsgi.cpython-36.pyc create mode 100644 academy/apps/__init__.py create mode 100644 academy/apps/__pycache__/__init__.cpython-36.pyc create mode 100644 academy/apps/accounts/__init__.py create mode 100644 academy/apps/accounts/__pycache__/__init__.cpython-36.pyc create mode 100644 academy/apps/accounts/__pycache__/admin.cpython-36.pyc create mode 100644 academy/apps/accounts/__pycache__/models.cpython-36.pyc create mode 100644 academy/apps/accounts/admin.py create mode 100644 academy/apps/accounts/apps.py create mode 100644 academy/apps/accounts/migrations/0001_initial.py create mode 100644 academy/apps/accounts/migrations/__init__.py create mode 100644 academy/apps/accounts/migrations/__pycache__/0001_initial.cpython-36.pyc create mode 100644 academy/apps/accounts/migrations/__pycache__/__init__.cpython-36.pyc create mode 100644 academy/apps/accounts/models.py create mode 100644 academy/apps/accounts/views.py create mode 100644 academy/core/__init__.py create mode 100644 academy/core/__pycache__/__init__.cpython-36.pyc create mode 100644 academy/core/__pycache__/custom_auth.cpython-36.pyc create mode 100644 academy/core/__pycache__/utils.cpython-36.pyc create mode 100644 academy/core/__pycache__/validators.cpython-36.pyc create mode 100644 academy/core/custom_auth.py create mode 100644 academy/core/utils.py create mode 100644 academy/core/validators.py create mode 100644 academy/settings.py create mode 100644 academy/urls.py create mode 100644 academy/wsgi.py create mode 100644 db.sqlite3 create mode 100755 manage.py create mode 100644 requirements.txt diff --git a/academy/__init__.py b/academy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/academy/__pycache__/__init__.cpython-36.pyc b/academy/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ac60df57fc32fbce3f24275f245900d11da23c6 GIT binary patch literal 143 zcmXr!<>lIBTouIt1dl-k3@`#24nSPY0whuxf*CX!{Z=v*frJsnFB|>P;?$yI{mi1Y z#JqyioK$_6{N&Qy)Vz{neW#MtcAN_V0tvUpzy=Z^QUWR1+M-w#TM1r#Nm(*k^nglMj~xX|G8%~x zz2-Ogf&Ha<-KYJ8=^mLD&&(9bCc@=8Kg-qtJ%-FAh^c#Gr zkj-Quqh%lqTtBO2N%n|4ni`vVGJTqjhL%gYxYqJ1okzM5(=()ibTOu9Ndcx#Ic*Mj zZ62nz1;}ZadKqmI@=$;oD8ekv!8|PV3fg731dDJPuE14Tf@{6Jb_K3$S7EuAfgG&B z4Y&!n;C7F^m<+@qzUg{$cBJSrta7t!<%MdYX z#mbT4^xP69zHd1_TI#x9$uJEd_DN~rxktqGg<^4!IK(r20;SGL=@G;>8wS{xQ=-1% z`KjikQa}-Q3Thd zLgHi?g6Y~Kal{Bw^xc7FQgIlvnBe<|q|^=i{Zikee#z~gZOL!|JrT<*eKGn0q5sR7 zN4jI4{*H>T!KQ5jmJ#N~_$`LdoQ*fmOSre{82282G-3PWs?lEyw^yHi`Mep}-jnW$ zZolZ+=Gvyd9enKs$6wWODcPZ5x{mKz9U)FEUBo9tp1vSH@sK1;aGm!0~CgkpkEjK%X2N9uX)p z1JCkL1SKWvBU!jT=`W2?7_(Or-k8<;c_&x}w(AJx`1K#E)awdmoZegHcue)>L@Wm8 zcRUUW*O*$%jEi*4aB>sFY>pe(lMIhpz4*Z<`j+|W$S^-)rwD)SdWKD!gQz3unBC|Y z0)RUGB>2gp&L!{-yqqa6OgU?^MXS$;<g%zazeLbe~ z&3(1nY$)N%uuhL@&l0d$F~{)%vOJKk5%m30(L?7fd-QYP^2zhCh|H8;=U7f|>{S~w z;~P?4_KMi?;oFJ8g48#j>rw5p~7;M8oyM*B3>q zTaIN1c8xea|M1NIw~N{*O|qZHcn0w1q5zG+CZ1)UN0=Yp1MzOZuMTq`-57!yP~Wxn zI6<;)SpA)(RKscFYy^}|wbe4?s+F)H;+F&aOw{HQLXR&XmP=OaS#K6Izy5&bbsawl zy3RP4GJatAhj^%#=V0HkywRaCr=Z8?x~>&=Bt?$OLz`1%RjoGmlw`HvYW^;lRlU`0 zs;tm4D2X7nxgkF~ZN?wDmcxp5xl)x9&6$L5w`#1Y$mN!->hI(aY`P-vwD;J&RI4=) z9Jsnp~HsU@?y$gz$%RWwZQj~*ctD?V`YE=|Au?;T8lC~nZ^m?-**VuBzkQ-`> zqNiP>u=$$Q*lSCBvR+0-bX~2>y4J)JFQBil}5Y!GvjUGp~chpS7Ou*RJ6RV;S7R45i72VHH9A#amOd- zp_mrV=sofcIsJB- literal 0 HcmV?d00001 diff --git a/academy/__pycache__/urls.cpython-36.pyc b/academy/__pycache__/urls.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..670261259c931a8f7e95ed29e23f01d14b9e1da5 GIT binary patch literal 933 zcma)5!H&}~5KYo_yM$ff6MR5QBbAu47gPZP7FMi;H~@ReVY6=Rw60=1vK^qk@-YsE#F=^X=8b)Fd>nm0*<`;1&->x+Jp=Hc!)qRbpNtkK2$x9C*Kk}n!fELSp$ zJ}w!$YIIc-Ynhhj3RT=#q*Y^?aR~-lg+6ii*`(-9X(W_ph|5xG(LtcPV#F|H7@I{1 zo~5<5nPE&-VN$vxa-nLiR;;jTp#)|UPt)lXTUGPIU>A*{zQNJ!FGK*CnMG%fEF8UU z-41n{q8F4RA`ut0(sqVWsg*!tos+uWZSKWC+QoN0LkD{;LMnWXb$oe0p6ps%D#0d5 z62YFv&X1Gmv?9hlm_u)L5BGmOlwC6IsHB}%J)t*%)$zYEAD595lRKDka*fluEUJcb zxd0)$imtr^CfaLs-id>N49v*IvT=gSot(3+WZRj*Fl3oJ<$JE+Px`EzbDmdffkDT< zTQq_t)R+~-*~ z^#s1Q#(^V#3FJ_~lww~L5atLYjS*`F&lGGxkqxtQpVF)WK^6ruECexTY2OoJQ;s@JDXgU^ULe&>1;ADKV6M)K3?w5@7vEE zcrSJBhW*el%jlsj12!(4ADrYoHjsC;7Du7b2fdNj=#a%i0To*-A08Yjen&QoANTO* z1-)@#9hJ6Xx{afwW5d^-dq>}S;7fXMhxifx3(-8R AM*si- literal 0 HcmV?d00001 diff --git a/academy/apps/__init__.py b/academy/apps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/academy/apps/__pycache__/__init__.cpython-36.pyc b/academy/apps/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e415b322cad2a01ee228d1f551e7d4c5fa5bd9f GIT binary patch literal 148 zcmXr!<>fkUSrx?q1dl-k3@`#24nSPY0whuxf*CX!{Z=v*frJsnFGu~*;?$yI{mi1Y z#JqyioK$_6{N&Qy)Vz{neW#MtwWOOkQGXMbU7bO?~ literal 0 HcmV?d00001 diff --git a/academy/apps/accounts/__init__.py b/academy/apps/accounts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/academy/apps/accounts/__pycache__/__init__.cpython-36.pyc b/academy/apps/accounts/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82fb2c81a49c374cdb3bc015134d13cff8afafc8 GIT binary patch literal 157 zcmXr!<>i`YQWeDj1dl-k3@`#24nSPY0whuxf*CX!{Z=v*frJsnFE9Pj;?$yI{mi1Y z#JqyioK$_6{N&Qy)Vz{neW#MtF4FNHr*S literal 0 HcmV?d00001 diff --git a/academy/apps/accounts/__pycache__/admin.cpython-36.pyc b/academy/apps/accounts/__pycache__/admin.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ec93ed4f5d3fa136d784a9ce0b917e2d0fcde3d GIT binary patch literal 1145 zcmZuw&2H2%5RQ{r<8DT!#6{PYZWS{LhmIB*%Y#Z1CvMS62c9@5ZKyXJI zOLS?YN^r@H9q^h8Y2zO5ZfMPI+)`t{E6r}lS6my_P>#{A*hSa_ znE84i`2q4^Xt)w?U zJ^c!OBm6#JV28~@=!!NixLKU3vafm5nZ?JBm#YOWDdY9c)7rKMgi`fr<3?xR-nbTG zga#9h{gk96BoUbeZs*zL;B1|uDVE^x$k~Z&LxG5SUCxL;hGVl( zAHt%K5MBbB;54{s8H&DRTe- literal 0 HcmV?d00001 diff --git a/academy/apps/accounts/__pycache__/models.cpython-36.pyc b/academy/apps/accounts/__pycache__/models.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62f056411973ce2dea01c270fb1bf5e999707706 GIT binary patch literal 2382 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 K4xSY}UiJUM820`E literal 0 HcmV?d00001 diff --git a/academy/apps/accounts/migrations/__pycache__/__init__.cpython-36.pyc b/academy/apps/accounts/migrations/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ee508f2be05187eb7e93bec5089ecffc9d016eb GIT binary patch literal 168 zcmXr!<>jifs)}L&g2x~N1{i@12OutH0TL+;!3>&=ek&P@K*9*(SEznyacWVqer8cx zVqQUMPO833esXDUYF)C@2PUlJiSJYH~BvixNvR^Ye=J efkWRu#nn1dl-k3@`#24nSPY0whuxf*CX!{Z=v*frJsnFGu~*;?$yI{mi1Y z#JqyioK$_6{N&Qy)Vz{neW#Mt2 PKLx1M4rFvO5HkP(=};vO literal 0 HcmV?d00001 diff --git a/academy/core/__pycache__/custom_auth.cpython-36.pyc b/academy/core/__pycache__/custom_auth.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df0c9fb751bed13b5e23b323bbe66c708ebaacb7 GIT binary patch literal 1003 zcmZuwPjAyO6!)`}EM(bKZ7>N5ao|KQ?STtI6Pm^*PV~Tpm~x4-*zMBhPq9;tPTgs{ z!uQ}S`O1k4A7CfmOVq9i9KGkC?f1_=zr5Pn34R}5$DUy9C)*ef;v*FE8kJ-c3RXf4 zK$sW26tQTrD4f!bU10B-bfkO7q^sao#GdrdShV#Ey;%e{{7_3(9H-e-RT9^}QB9Lq zV}p2iteRwQluk-A%E)Cku&l0(=Li&wL9&=jPjV^lAQoN9*pWcVY+<1C$tSn^xYZ5X zhc(W`od)_NF#04rW9O}ooZ&qjSyxdR)~7pFX{jPl6P?QV9dvS~6) zjk&6|w9Y3qx8X^x%&=}wzviZiTYg{@T==UZr|$tV0=oFujMz_a_4iU~fH1sZ`}+J!iF6gKTb^x=hk}bJ?FQY)Alo@+@ssfN>24 zXW&D?ec;f80C5klpKfy9-}K5jdElUV&3hjgi{6UeB}n*&kA_?l-vZfu`45|Xh~2?w z)5vN0(~mHOrkeB)s)*}d!o*F>K&SR`Y5i489pK841#4^HgX<@M)xENd_;849`$<9% zmLxVvs2h<*#9@+rnWsf}q90>0O>sAp5=WXcYwEQv6hklWiy&-whS;3Xszpwhm699ZM_9eNyVfa%f%1Kc6CKf>Q0m@O7CTK1ACRN5r z&+i!ijETe!-hr|Y`6_mT2jr|jsH}Q69{VFK=2%!P=o88;j$3C|)l1A<71l1T8t7+= zkKQc$!DLRI^Vb{o%!yk*zcjiO~*p1$jI iCJ-mWjag@LpeI1(o9RxENNemx*niwhZ2|?XVXlnYV)~&=!D}F`mm86>1d|T_)WG;1lN9(nu zo;Li3*6pO3w)}S5@#kSY$DHSeUt@LFfPR5BSqu7W-x{pVI?oN(;q7zNZ^3w;Ex>qz z&%?OG$iCrSdkG#IJ&zRaVL#7!HcAh<7^ygcsmd@El7nJPu2h^INzhwAhe^yr#RHy( zdRhDXawg8REg^D&8%9U4gFjUsEtc-ZS)7j29iAPj{$y<~isjxY5gx2VQAba%y2!=nENDFeRs9H z>fU0x@;-Hk2@fTAqdt$0-S8-kvjfj8uCqay9p%9+u%Ze#Dr_(#(Tqm~-c@5;3dBV? zAUe=w3xq)^X^<9KrVeqa{x$^*k(`3{7Yvj!AdDPS@gu-SF~VmAU|Rv$%z*{KeLexM z!YINrfr|{PVx5`$2wY7A_d?mYn^lf2@dCeO4^I}<+yHFi8Rztj&e;9sD!Xu|a|-92 znV{7N4K15T^vpUnPp#u>X<1Et(ZQ+q3c9^H_V!9pA+flaMk&n?bVRx~b^u`KH4fq^<1a=*QY6<(S>z=`U;-Mia6TmIrV+Yh%kgPrZ(R;{Lu%!kr~DHX*!io2im|puwUK;VL*;xwsc5~R*7XU zkt(HR0msBKtI%v>QSlzEjBxqI4^di&CKo|)!zaw}DI<&m`I#7f&k~67H1Uv55bX_U zash;bDrArx0}_*^l32{%_{$4Ia?_DiZj@&V%EJwni{Vx7$G6fr3jk|iGmk+Dg(8d~ z;<8&fm%dO@gCoQW2rNy>lgDoY(*%+X`aBs1NR@ZcEi5%G9!ka^UCo=_nN2;eFR=ddym%uOmOTiinnk*PWkPal}TKdgw$nQ)Jyj4 zLdHBU%X(=#BY1aG1@NBe$3x76rDA3UzbJEAQtt9(J3hyzNYq zVK*G9es?%|O)oecNdtr6zq_fq{pzIBSM*oPCI1Derg2?|SD{wecgo!R8tY6hgRr5h R8x)%UcP!hq>$cmm{{a$fN~Hh* literal 0 HcmV?d00001 diff --git a/academy/core/custom_auth.py b/academy/core/custom_auth.py new file mode 100644 index 0000000..db50b70 --- /dev/null +++ b/academy/core/custom_auth.py @@ -0,0 +1,26 @@ +from django.contrib.auth.backends import ModelBackend + +from django.conf import settings +from django.contrib.auth import get_user_model + + +class EmailBackend(ModelBackend): + # Authenticate user using email + + def authenticate(self, username=None, password=None): + if '@' in username: + kwargs = {'email': username} + else: + kwargs = {'username': username} + try: + user = get_user_model().objects.get(**kwargs) + if user.check_password(password): + return user + except User.DoesNotExist: + return None + + def get_user(self, username): + try: + return get_user_model().objects.get(pk=username) + except get_user_model().DoesNotExist: + return None \ No newline at end of file diff --git a/academy/core/utils.py b/academy/core/utils.py new file mode 100644 index 0000000..fc603c9 --- /dev/null +++ b/academy/core/utils.py @@ -0,0 +1,3 @@ +def image_upload_path(prefix='etc'): + path = f"images/{prefix}/%Y/%m/%d" + return path \ No newline at end of file diff --git a/academy/core/validators.py b/academy/core/validators.py new file mode 100644 index 0000000..7598719 --- /dev/null +++ b/academy/core/validators.py @@ -0,0 +1,69 @@ +import phonenumbers +from phonenumbers import phonenumberutil +from id_phonenumbers import parse + +from django.conf import settings +from django.core.validators import validate_email as django_validate_email +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext +from django.contrib.auth.password_validation import (MinimumLengthValidator as DjangoMinimumLengthValidator, + NumericPasswordValidator as DjangoNumericPasswordValidator) + + +def validate_email(email): + return validate_email_address(email) + +def validate_email_address(email): + try: + django_validate_email(email) + except ValidationError: + raise ValidationError(f'{email} is not a valid email', code='invalid') + + if email.endswith('.'): + raise ValidationError('Email cannot end with \'.\' (dot), please check again') + else: + return True + +def validate_mobile_phone(phone_number): + # Indonesia only accept mobile phone + if settings.COUNTRY == 'ID': + try: + number = parse(phone_number) + except phonenumberutil.NumberParseException: + raise ValidationError('Please enter a valid mobile phone number.') + + if number.is_mobile: + return True + + # International phone numbers are accepted + if phone_number.startswith('+') and len(phone_number) > 8: + return True + else: + try: + phone = phonenumbers.parse(phone_number, settings.COUNTRY) + except phonenumberutil.NumberParseException: + raise ValidationError('Please enter a valid mobile phone number.') + number_type = phonenumberutil.number_type(phone) + + accepted_mobile_type = [ + phonenumberutil.PhoneNumberType.MOBILE, + phonenumberutil.PhoneNumberType.FIXED_LINE_OR_MOBILE, + ] + + if number_type in accepted_mobile_type: + return True + + raise ValidationError('Please enter a valid mobile phone number.') + + +class MinimumLengthValidator(DjangoMinimumLengthValidator): + def get_help_text(self): + return ugettext( + "Password must contain at least %(min_length)d characters." + % {'min_length': self.min_length} + ) + + +class NumericPasswordValidator(DjangoNumericPasswordValidator): + def get_help_text(self): + return ugettext("Password can't be entirely numeric.") diff --git a/academy/settings.py b/academy/settings.py new file mode 100644 index 0000000..99fc2c3 --- /dev/null +++ b/academy/settings.py @@ -0,0 +1,137 @@ +""" +Django settings for academy project. + +Generated by 'django-admin startproject' using Django 1.11.1. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +SETTINGS_DIR = os.path.dirname(__file__) +PROJECT_ROOT = os.path.dirname(SETTINGS_DIR) +PROJECT_NAME = os.path.basename(PROJECT_ROOT) + +MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media') +MEDIA_URL = '/media/' +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'n-@n7d!%na!&^cd4^%al(z4%2vq0umr+fy_m6gmc(0_4uxbuwx' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'academy.core', + 'academy.apps.accounts', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'academy.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'academy.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +AUTH_USER_MODEL = 'accounts.User' +AUTHENTICATION_BACKENDS = ( + 'academy.core.custom_auth.EmailBackend', +) + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +COUNTRY = 'ID' + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, 'static_files'), +) +STATIC_ROOT = os.path.join(SETTINGS_DIR, 'static') diff --git a/academy/urls.py b/academy/urls.py new file mode 100644 index 0000000..d02fcbe --- /dev/null +++ b/academy/urls.py @@ -0,0 +1,21 @@ +"""academy URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] diff --git a/academy/wsgi.py b/academy/wsgi.py new file mode 100644 index 0000000..564f16d --- /dev/null +++ b/academy/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for academy project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "academy.settings") + +application = get_wsgi_application() diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..b7b4baae0736ff2ce205c40a68f8e810bfe08853 GIT binary patch literal 143360 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 B^hy8# literal 0 HcmV?d00001 diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..0a1fd64 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "academy.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..47dfd7b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +Django==1.11 +psycopg2==2.7.3.2 + +id-phonenumbers==0.3.0 +phonenumbers==8.8.10 +django-model-utils==3.0.0 +Pillow==4.3.0 \ No newline at end of file