package service import ( "context" "crypto/rsa" "encoding/json" "fmt" "reflect" "time" "strings" cda "git.loafle.net/commons/di-go/annotation" cdr "git.loafle.net/commons/di-go/registry" "git.loafle.net/commons/logging-go" "git.loafle.net/commons/server-go" "git.loafle.net/overflow/external-go/grpc" "github.com/dgrijalva/jwt-go" "github.com/valyala/fasthttp" // For annotation _ "git.loafle.net/overflow/commons-go/core/annotation" ) var MemberServiceType = reflect.TypeOf((*MemberService)(nil)) func init() { cdr.RegisterType(MemberServiceType) } type MemberService struct { cda.TypeAnnotation `annotation:"@overflow:RESTService()"` VerifyKey *rsa.PublicKey `annotation:"@Resource(name='VerifyKey')"` SignKey *rsa.PrivateKey `annotation:"@Resource(name='SignKey')"` _Signin cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/signin', params='[signinID, signinPW]')"` _SigninByCookie cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/signin_cookie', params='[authToken]')"` _Signup cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/signup', params='[member, password]')"` _ConfirmEmail cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/confirm_email', params='[token]')"` _SendEmailPw cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/send_email_pw', params='[signinID]')"` _ConfirmResetPw cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/confirm_reset_pw', params='[token]')"` _ResetPassword cda.MethodAnnotation `annotation:"@overflow:RequestMapping(method='POST', entry='/account/reset_password', params='[token, pw, confirmPw]')"` } type SigninResult struct { AuthToken string `json:"authToken"` DomainMember interface{} `json:"domainMember"` } func (ms *MemberService) Signin(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, signinID string, signinPW string) error { gRPCCtx := context.Background() r, err := grpc.Exec(gRPCCtx, "MemberService.signin", signinID, signinPW) if nil != err { return err } token := jwt.New(jwt.SigningMethodRS512) /* Create a map to store our claims */ claims := token.Claims.(jwt.MapClaims) // expireTime := time.Now().Add(time.Hour * 24) /* Set token claims */ claims["iss"] = "overFlow" claims["iat"] = time.Now().Unix() claims["exp"] = time.Now().Add(time.Hour * 24).Unix() claims["aud"] = "www.overflow.cloud" claims["sub"] = signinID /* Sign the token with our secret */ tokenString, err := token.SignedString(ms.SignKey) if nil != err { return err } var domainMember interface{} err = json.Unmarshal([]byte(r), &domainMember) if nil != err { return err } signInResult := &SigninResult{ AuthToken: tokenString, DomainMember: domainMember, } buf, err := json.Marshal(signInResult) if nil != err { return err } ctx.SetBody(buf) return nil } func (ms *MemberService) SigninByCookie(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, authToken string) error { token, err := jwt.Parse(authToken, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("Webapp: Unexpected signing method: %v", token.Header["alg"]) } // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key") return ms.VerifyKey, nil }) if nil != err { return err } var ok bool var claims jwt.MapClaims if claims, ok = token.Claims.(jwt.MapClaims); !ok || !token.Valid { logging.Logger().Warnf("Token is not valid %v", token) return fmt.Errorf("authToken is not valid") } params := []string{claims["sub"].(string)} gRPCCtx := context.Background() r, err := grpc.Exec(gRPCCtx, "DomainMemberService.readByMemberEmail", params...) if nil != err { return err } ctx.SetBody([]byte(r)) return nil } func (ms *MemberService) Signup(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, member string, pw string) error { gRPCCtx := context.Background() r, err := grpc.Exec(gRPCCtx, "MemberService.signup", member, pw) if nil != err { return err } ctx.SetBody([]byte(r)) return nil } func (ms *MemberService) SendEmailPw(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, signinID string) error { gRPCCtx := context.Background() r, err := grpc.Exec(gRPCCtx, "MemberService.sendEmailForPassword", signinID) if nil != err { return err } ctx.SetBody([]byte(r)) return nil } func (ms *MemberService) ConfirmEmail(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, token string) error { gRPCCtx := context.Background() r, err := grpc.Exec(gRPCCtx, "EmailAuthService.readBySignupAuthKey", token) if nil != err { return err } //uri := ccm.NG_MEMBER_SERVER_URI + "/auth/signin" //ctx.Redirect(uri, 302) ctx.SetBody([]byte(r)) return nil } func (ms *MemberService) ConfirmResetPw(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, token string) error { gRPCCtx := context.Background() r, err := grpc.Exec(gRPCCtx, "EmailAuthService.readByPwAuthKey", token) if nil != err { return err } //uri := ccm.NG_MEMBER_SERVER_URI + "/auth/modify-password?token=" + token //ctx.Redirect(uri, 302) ctx.SetBody([]byte(r)) return nil } func (ms *MemberService) ResetPassword(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx, token string, pw string, confirmPw string) error { gRPCCtx := context.Background() if strings.Compare(pw, confirmPw) != 0 { return fmt.Errorf("ResetPassword() password not match: %s, %s", pw, confirmPw) } r, err := grpc.Exec(gRPCCtx, "MemberService.resetPassword", token, pw) if nil != err { return err } //uri := ccm.NG_MEMBER_SERVER_URI + "/auth/signin" //ctx.Redirect(uri, 302) ctx.SetBody([]byte(r)) return nil }