diff --git a/backend/graph/generated/generated.go b/backend/graph/generated/generated.go index 13c405b..9fda096 100644 --- a/backend/graph/generated/generated.go +++ b/backend/graph/generated/generated.go @@ -46,8 +46,14 @@ type DirectiveRoot struct { } type ComplexityRoot struct { + LogoutResponse struct { + Message func(childComplexity int) int + Status func(childComplexity int) int + } + Mutation struct { LoginAttendance func(childComplexity int, email string, idGoogleSignIn string) int + LogoutAttendance func(childComplexity int, email string, idGoogleSignIn string) int MutationClockInAttendance func(childComplexity int, tTransactionMStaffID string, tTransactionMCompanyID string, tTransactionCurrentLatitude string, tTransactionCurrentLongitude string, tTransactionCurrentDistance string, tTransactionSelfiePhoto *string, token string, isSelfie string) int MutationClockOutAttendance func(childComplexity int, tTransactionMStaffID string, tTransactionMCompanyID string, tTransactionCurrentLatitude string, tTransactionCurrentLongitude string, tTransactionCurrentDistance string, tTransactionSelfiePhoto *string, token string, isSelfie string) int } @@ -109,6 +115,7 @@ type ComplexityRoot struct { type MutationResolver interface { LoginAttendance(ctx context.Context, email string, idGoogleSignIn string) (*model.Staff, error) + LogoutAttendance(ctx context.Context, email string, idGoogleSignIn string) (*model.LogoutResponse, error) MutationClockInAttendance(ctx context.Context, tTransactionMStaffID string, tTransactionMCompanyID string, tTransactionCurrentLatitude string, tTransactionCurrentLongitude string, tTransactionCurrentDistance string, tTransactionSelfiePhoto *string, token string, isSelfie string) (*model.TransAbsensiResponse, error) MutationClockOutAttendance(ctx context.Context, tTransactionMStaffID string, tTransactionMCompanyID string, tTransactionCurrentLatitude string, tTransactionCurrentLongitude string, tTransactionCurrentDistance string, tTransactionSelfiePhoto *string, token string, isSelfie string) (*model.TransAbsensiResponse, error) } @@ -139,6 +146,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { + case "LogoutResponse.message": + if e.complexity.LogoutResponse.Message == nil { + break + } + + return e.complexity.LogoutResponse.Message(childComplexity), true + + case "LogoutResponse.status": + if e.complexity.LogoutResponse.Status == nil { + break + } + + return e.complexity.LogoutResponse.Status(childComplexity), true + case "Mutation.loginAttendance": if e.complexity.Mutation.LoginAttendance == nil { break @@ -151,6 +172,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.LoginAttendance(childComplexity, args["email"].(string), args["id_google_sign_in"].(string)), true + case "Mutation.logoutAttendance": + if e.complexity.Mutation.LogoutAttendance == nil { + break + } + + args, err := ec.field_Mutation_logoutAttendance_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.LogoutAttendance(childComplexity, args["email"].(string), args["id_google_sign_in"].(string)), true + case "Mutation.mutationClockInAttendance": if e.complexity.Mutation.MutationClockInAttendance == nil { break @@ -582,6 +615,13 @@ type TokenResponse { message: String } + +# logout response +type LogoutResponse { + status:String + message:String +} + # query search extend type Query { searchStaffByEmail(email: String!): Staff! @@ -591,7 +631,11 @@ extend type Query { # mutation untuk perubahan data extend type Mutation { + # login loginAttendance(email:String!, id_google_sign_in:String!) : Staff! + + # logout + logoutAttendance(email:String!, id_google_sign_in:String!) : LogoutResponse! }`, BuiltIn: false}, {Name: "../graphqls/transabsensi.graphqls", Input: `# response error atau success dan set message type TransAbsensiResponse { @@ -667,6 +711,30 @@ func (ec *executionContext) field_Mutation_loginAttendance_args(ctx context.Cont return args, nil } +func (ec *executionContext) field_Mutation_logoutAttendance_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["email"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["email"] = arg0 + var arg1 string + if tmp, ok := rawArgs["id_google_sign_in"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id_google_sign_in")) + arg1, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id_google_sign_in"] = arg1 + return args, nil +} + func (ec *executionContext) field_Mutation_mutationClockInAttendance_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1014,6 +1082,88 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg // region **************************** field.gotpl ***************************** +func (ec *executionContext) _LogoutResponse_status(ctx context.Context, field graphql.CollectedField, obj *model.LogoutResponse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_LogoutResponse_status(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Status, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_LogoutResponse_status(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LogoutResponse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _LogoutResponse_message(ctx context.Context, field graphql.CollectedField, obj *model.LogoutResponse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_LogoutResponse_message(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Message, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_LogoutResponse_message(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LogoutResponse", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Mutation_loginAttendance(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_loginAttendance(ctx, field) if err != nil { @@ -1101,6 +1251,67 @@ func (ec *executionContext) fieldContext_Mutation_loginAttendance(ctx context.Co return fc, nil } +func (ec *executionContext) _Mutation_logoutAttendance(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_logoutAttendance(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().LogoutAttendance(rctx, fc.Args["email"].(string), fc.Args["id_google_sign_in"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.LogoutResponse) + fc.Result = res + return ec.marshalNLogoutResponse2ᚖcomᚗsismedikaᚗcomᚗabsensiᚋgraphᚋmodelᚐLogoutResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_logoutAttendance(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "status": + return ec.fieldContext_LogoutResponse_status(ctx, field) + case "message": + return ec.fieldContext_LogoutResponse_message(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type LogoutResponse", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_logoutAttendance_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_mutationClockInAttendance(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_mutationClockInAttendance(ctx, field) if err != nil { @@ -4821,6 +5032,44 @@ func (ec *executionContext) fieldContext___Type_specifiedByURL(ctx context.Conte // region **************************** object.gotpl **************************** +var logoutResponseImplementors = []string{"LogoutResponse"} + +func (ec *executionContext) _LogoutResponse(ctx context.Context, sel ast.SelectionSet, obj *model.LogoutResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, logoutResponseImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("LogoutResponse") + case "status": + out.Values[i] = ec._LogoutResponse_status(ctx, field, obj) + case "message": + out.Values[i] = ec._LogoutResponse_message(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var mutationImplementors = []string{"Mutation"} func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -4847,6 +5096,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "logoutAttendance": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_logoutAttendance(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "mutationClockInAttendance": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_mutationClockInAttendance(ctx, field) @@ -5650,6 +5906,20 @@ func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.Selec return res } +func (ec *executionContext) marshalNLogoutResponse2comᚗsismedikaᚗcomᚗabsensiᚋgraphᚋmodelᚐLogoutResponse(ctx context.Context, sel ast.SelectionSet, v model.LogoutResponse) graphql.Marshaler { + return ec._LogoutResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNLogoutResponse2ᚖcomᚗsismedikaᚗcomᚗabsensiᚋgraphᚋmodelᚐLogoutResponse(ctx context.Context, sel ast.SelectionSet, v *model.LogoutResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._LogoutResponse(ctx, sel, v) +} + func (ec *executionContext) marshalNStaff2comᚗsismedikaᚗcomᚗabsensiᚋgraphᚋmodelᚐStaff(ctx context.Context, sel ast.SelectionSet, v model.Staff) graphql.Marshaler { return ec._Staff(ctx, sel, &v) } diff --git a/backend/graph/graphqls/staff.graphqls b/backend/graph/graphqls/staff.graphqls index b73c818..11527f4 100644 --- a/backend/graph/graphqls/staff.graphqls +++ b/backend/graph/graphqls/staff.graphqls @@ -23,6 +23,13 @@ type TokenResponse { message: String } + +# logout response +type LogoutResponse { + status:String + message:String +} + # query search extend type Query { searchStaffByEmail(email: String!): Staff! @@ -32,5 +39,9 @@ extend type Query { # mutation untuk perubahan data extend type Mutation { + # login loginAttendance(email:String!, id_google_sign_in:String!) : Staff! + + # logout + logoutAttendance(email:String!, id_google_sign_in:String!) : LogoutResponse! } \ No newline at end of file diff --git a/backend/graph/model/models_gen.go b/backend/graph/model/models_gen.go index be3f6a0..81e18a7 100644 --- a/backend/graph/model/models_gen.go +++ b/backend/graph/model/models_gen.go @@ -2,6 +2,11 @@ package model +type LogoutResponse struct { + Status *string `json:"status,omitempty"` + Message *string `json:"message,omitempty"` +} + type Mutation struct { } diff --git a/backend/graph/resolver/staff.resolvers.go b/backend/graph/resolver/staff.resolvers.go index e1f7ba4..f7ffc47 100644 --- a/backend/graph/resolver/staff.resolvers.go +++ b/backend/graph/resolver/staff.resolvers.go @@ -21,6 +21,13 @@ func (r *mutationResolver) LoginAttendance(ctx context.Context, email string, id return staffinternal.LoginAttendance(email, idGoogleSignIn) } +// LogoutAttendance is the resolver for the logoutAttendance field. +func (r *mutationResolver) LogoutAttendance(ctx context.Context, email string, idGoogleSignIn string) (*model.LogoutResponse, error) { + // panic(fmt.Errorf("not implemented: LogoutAttendance - logoutAttendance")) + var staffinternal staffinternal.Staff + return staffinternal.LogoutAttendance(email, idGoogleSignIn) +} + // SearchStaffByEmail is the resolver for the searchStaffByEmail field. func (r *queryResolver) SearchStaffByEmail(ctx context.Context, email string) (*model.Staff, error) { panic(fmt.Errorf("not implemented: SearchStaffByEmail - searchStaffByEmail")) diff --git a/backend/internal/staff/staff.go b/backend/internal/staff/staff.go index 8a7c876..b2fd35e 100644 --- a/backend/internal/staff/staff.go +++ b/backend/internal/staff/staff.go @@ -26,6 +26,7 @@ func (staff *Staff) LoginAttendance(email string, id_google_sign_in string) (*mo // inisialisasi var err error var ret model.Staff + var var_staff_is_login string // decode private.pem pemData, err := ioutil.ReadFile(config.Data.Get("privatekey")) @@ -55,32 +56,61 @@ func (staff *Staff) LoginAttendance(email string, id_google_sign_in string) (*mo return nil, err } - // jika sukses generate token maka update - // M_StaffToken & M_StaffIsLogin - - qx := `UPDATE m_staff - SET - M_StaffToken = ?, - M_StaffIsLogin = 'Y' - WHERE - M_StaffIsActive = 'Y' - AND M_StaffEmail = ? - AND M_StaffIDGoogleSignIn = ? + // check staff is login + qCheck := `SELECT + M_StaffIsLogin + FROM m_staff + WHERE + M_StaffIsActive = 'Y' + AND M_StaffEmail = ? ` - // log sql untuk mengetahui query yg akan dieksekusi - db.LogSQL(qx) - // cek kondisi - // _ merupakan kondisi true namun value tidak digunakan sbg cek - // error kondisi false dan error digunakan - _, err = db.Handle.Exec( - qx, - token, + rowCheck := db.Handle.QueryRow( + qCheck, email, - id_google_sign_in) + ) + + db.LogSQL(qCheck) + err = rowCheck.Scan( + &var_staff_is_login, + ) if err != nil { - return &ret, fmt.Errorf("UPDATE_TOKEN_FAILED") + log.Printf("Error m_staff select isLogin: %v", err) + log.Printf("Executing query: %s\n", qCheck) + return nil, err + } + + if var_staff_is_login == "N" { + // generate token jk isLogin N + + // jika sukses generate token maka update + // M_StaffToken & M_StaffIsLogin + + qx := `UPDATE m_staff + SET + M_StaffToken = ?, + M_StaffIDGoogleSignIn = ?, + M_StaffIsLogin = 'Y' + WHERE + M_StaffIsActive = 'Y' + AND M_StaffEmail = ? + ` + // log sql untuk mengetahui query yg akan dieksekusi + db.LogSQL(qx) + + // cek kondisi + // _ merupakan kondisi true namun value tidak digunakan sbg cek + // error kondisi false dan error digunakan + _, err = db.Handle.Exec( + qx, + token, + id_google_sign_in, + email) + + if err != nil { + return &ret, fmt.Errorf("UPDATE_TOKEN_FAILED") + } } // data yang akan di tampilkan @@ -147,3 +177,76 @@ func (staff *Staff) LoginAttendance(email string, id_google_sign_in string) (*mo // hasil return nya return &ret, err } + +// logout +func (staff *Staff) LogoutAttendance(email string, id_google_sign_in string) (*model.LogoutResponse, error) { + + // inisialisasi + var err error + var ret model.LogoutResponse + var varCheckToken string + + ret.Status = new(string) + ret.Message = new(string) + *ret.Status = "OK" + *ret.Message = "Logout Berhasil" + + q := `SELECT + M_StaffToken + FROM m_staff + join m_company + ON M_StaffM_CompanyID = M_CompanyID + AND M_CompanyIsActive = 'Y' + AND M_StaffIsActive = 'Y' + AND M_StaffIsLogin = 'Y' + AND M_StaffIDGoogleSignIn = ? + AND M_StaffEmail = ?` + + // row merupakan penerima yang akan dimasukkan langsung, menggunakan anotasi := + // id_google_sign_in, email merupakan binding parameter dari tanda tanya "?" di sql + row := db.Handle.QueryRow(q, id_google_sign_in, email) + db.LogSQL(q) + + // row.Scan untuk mendapatkan field dari sql diatas + // NOTE POSISI ROW SCAN HARUS SAMA PERSIS SEPERTI FIELD YANG AKAN DI RETURN + err = row.Scan( + &varCheckToken, + ) + + // check data + + if err != nil { + log.Printf("Error m_staff select: %v", err) + log.Printf("Executing query: %s\n", q) + *ret.Status = "ERR" + *ret.Message = "Error : Check Data Failed" + return &ret, err + } + + qx := `UPDATE m_staff + SET + M_StaffToken = NULL, + M_StaffIsLogin = 'N' + WHERE + M_StaffIsActive = 'Y' + AND M_StaffEmail = ? + ` + // log sql untuk mengetahui query yg akan dieksekusi + db.LogSQL(qx) + + // cek kondisi + // _ merupakan kondisi true namun value tidak digunakan sbg cek + // error kondisi false dan error digunakan + _, err = db.Handle.Exec( + qx, + email) + + if err != nil { + *ret.Status = "ERR" + *ret.Message = "Error : UPDATE TOKEN FAILED" + return &ret, fmt.Errorf("UPDATE_TOKEN_FAILED") + } + + // hasil return nya + return &ret, err +} diff --git a/backend/server b/backend/server index e5563dd..0e2ffdd 100644 Binary files a/backend/server and b/backend/server differ