github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/registry/impl_createlogin.go (about) 1 /* 2 * Copyright (c) 2021-present unTill Pro, Ltd. 3 * @author Denis Gribanov 4 */ 5 6 package registry 7 8 import ( 9 "errors" 10 "net/http" 11 "strings" 12 13 "github.com/voedger/voedger/pkg/appdef" 14 "github.com/voedger/voedger/pkg/goutils/iterate" 15 "github.com/voedger/voedger/pkg/istructs" 16 "github.com/voedger/voedger/pkg/istructsmem" 17 "github.com/voedger/voedger/pkg/state" 18 "github.com/voedger/voedger/pkg/sys/authnz" 19 coreutils "github.com/voedger/voedger/pkg/utils" 20 ) 21 22 // sys/registry, pseudoProfileWSID translated to appWSID 23 // creation of CDoc<Login> triggers opAsyncProjectorInvokeCreateWorkspaceID 24 func execCmdCreateLogin(asp istructs.IAppStructsProvider) istructsmem.ExecCommandClosure { 25 return func(args istructs.ExecCommandArgs) (err error) { 26 loginStr := args.ArgumentObject.AsString(authnz.Field_Login) 27 appName := args.ArgumentObject.AsString(authnz.Field_AppName) 28 29 subjectKind := istructs.SubjectKindType(args.ArgumentObject.AsInt32(authnz.Field_SubjectKind)) 30 if subjectKind >= istructs.SubjectKind_FakeLast || subjectKind <= istructs.SubjectKind_null { 31 return errors.New("wrong subject kind") 32 } 33 34 appQName, err := istructs.ParseAppQName(appName) 35 if err != nil { 36 return coreutils.NewHTTPErrorf(http.StatusBadRequest, "failed to parse app qualified name", appQName.String(), ":", err) 37 } 38 39 as, err := asp.AppStructs(appQName) 40 if err != nil { 41 if errors.Is(err, istructs.ErrAppNotFound) { 42 return coreutils.NewHTTPErrorf(http.StatusBadRequest, "unknown application ", appName) 43 } 44 return err 45 } 46 47 // still need this check after https://github.com/voedger/voedger/issues/1311: the command is tkaen from AppWS, number of AppWS related to the login is checked here 48 if err = CheckAppWSID(loginStr, args.WSID, as.NumAppWorkspaces()); err != nil { 49 return 50 } 51 52 // see https://dev.untill.com/projects/#!537026 53 if strings.HasPrefix(loginStr, "-") || strings.HasPrefix(loginStr, ".") || strings.HasPrefix(loginStr, " ") || 54 strings.HasSuffix(loginStr, "-") || strings.HasSuffix(loginStr, ".") || strings.HasSuffix(loginStr, " ") || 55 strings.Contains(loginStr, "..") || !validLoginRegexp.MatchString(loginStr) { 56 return coreutils.NewHTTPErrorf(http.StatusBadRequest, "incorrect login format: ", loginStr) 57 } 58 59 cdocLoginID, err := GetCDocLoginID(args.State, args.WSID, appName, loginStr) 60 if err != nil { 61 return err 62 } 63 if cdocLoginID > 0 { 64 return coreutils.NewHTTPErrorf(http.StatusConflict, "login already exists") 65 } 66 67 wsKindInitializationData := args.ArgumentObject.AsString(authnz.Field_WSKindInitializationData) 68 pwdSaltedHash, err := GetPasswordSaltedHash(args.ArgumentUnloggedObject.AsString(field_Passwrd)) 69 if err != nil { 70 return err 71 } 72 profileCluster := args.ArgumentObject.AsInt32(authnz.Field_ProfileCluster) 73 74 kb, err := args.State.KeyBuilder(state.Record, QNameCDocLogin) 75 if err != nil { 76 return err 77 } 78 cdocLogin, err := args.Intents.NewValue(kb) 79 if err != nil { 80 return err 81 } 82 cdocLogin.PutInt32(authnz.Field_ProfileCluster, profileCluster) 83 cdocLogin.PutBytes(field_PwdHash, pwdSaltedHash) 84 cdocLogin.PutString(authnz.Field_AppName, appName) 85 cdocLogin.PutInt32(authnz.Field_SubjectKind, args.ArgumentObject.AsInt32(authnz.Field_SubjectKind)) 86 cdocLogin.PutString(authnz.Field_LoginHash, GetLoginHash(loginStr)) 87 cdocLogin.PutRecordID(appdef.SystemField_ID, 1) 88 cdocLogin.PutString(authnz.Field_WSKindInitializationData, wsKindInitializationData) 89 90 return 91 } 92 } 93 94 // sys/registry, appWorkspace, triggered by CDoc<Login> 95 var projectorLoginIdx = func(event istructs.IPLogEvent, s istructs.IState, intents istructs.IIntents) (err error) { 96 return iterate.ForEachError(event.CUDs, func(rec istructs.ICUDRow) error { 97 if rec.QName() != QNameCDocLogin { 98 return nil 99 } 100 kb, err := s.KeyBuilder(state.View, QNameViewLoginIdx) 101 if err != nil { 102 return err 103 } 104 kb.PutInt64(field_AppWSID, int64(event.Workspace())) 105 kb.PutString(field_AppIDLoginHash, rec.AsString(authnz.Field_AppName)+"/"+rec.AsString(authnz.Field_LoginHash)) 106 107 vb, err := intents.NewValue(kb) 108 if err != nil { 109 return err 110 } 111 vb.PutInt64(field_CDocLoginID, int64(rec.AsRecordID(appdef.SystemField_ID))) 112 return nil 113 }) 114 }