Skip to content

Commit bf4bc95

Browse files
authored
NOLOGIN option in queries CREATE/ALTER USER (#12957)
Implementation in kqp, schemeshard and login provider of query 'CREATE/ALTER USER LOGIN/NOLOGIN'
1 parent eb9d335 commit bf4bc95

File tree

23 files changed

+392
-71
lines changed

23 files changed

+392
-71
lines changed

ydb/core/kqp/gateway/kqp_ic_gateway.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,8 @@ class TKikimrIcGateway : public IKqpGateway {
13711371
createUser.SetPassword(settings.Password);
13721372
}
13731373

1374+
createUser.SetCanLogin(settings.CanLogin);
1375+
13741376
SendSchemeRequest(ev.Release()).Apply(
13751377
[createUserPromise](const TFuture<TGenericResult>& future) mutable {
13761378
createUserPromise.SetValue(future.GetValue());
@@ -1410,8 +1412,13 @@ class TKikimrIcGateway : public IKqpGateway {
14101412
auto& alterUser = *schemeTx.MutableAlterLogin()->MutableModifyUser();
14111413

14121414
alterUser.SetUser(settings.UserName);
1413-
if (settings.Password) {
1414-
alterUser.SetPassword(settings.Password);
1415+
1416+
if (settings.Password.has_value()) {
1417+
alterUser.SetPassword(settings.Password.value());
1418+
}
1419+
1420+
if (settings.CanLogin.has_value()) {
1421+
alterUser.SetCanLogin(settings.CanLogin.value());
14151422
}
14161423

14171424
SendSchemeRequest(ev.Release()).Apply(

ydb/core/kqp/host/kqp_gateway_proxy.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,11 +1497,14 @@ class TKqpGatewayProxy : public IKikimrGateway {
14971497
schemeTx.SetWorkingDir(database);
14981498
schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin);
14991499
auto& createUser = *schemeTx.MutableAlterLogin()->MutableCreateUser();
1500+
15001501
createUser.SetUser(settings.UserName);
15011502
if (settings.Password) {
15021503
createUser.SetPassword(settings.Password);
15031504
}
15041505

1506+
createUser.SetCanLogin(settings.CanLogin);
1507+
15051508
auto& phyQuery = *SessionCtx->Query().PreparingQuery->MutablePhysicalQuery();
15061509
auto& phyTx = *phyQuery.AddTransactions();
15071510
phyTx.SetType(NKqpProto::TKqpPhyTx::TYPE_SCHEME);
@@ -1532,9 +1535,15 @@ class TKqpGatewayProxy : public IKikimrGateway {
15321535
schemeTx.SetWorkingDir(database);
15331536
schemeTx.SetOperationType(NKikimrSchemeOp::ESchemeOpAlterLogin);
15341537
auto& alterUser = *schemeTx.MutableAlterLogin()->MutableModifyUser();
1538+
15351539
alterUser.SetUser(settings.UserName);
1536-
if (settings.Password) {
1537-
alterUser.SetPassword(settings.Password);
1540+
1541+
if (settings.Password.has_value()) {
1542+
alterUser.SetPassword(settings.Password.value());
1543+
}
1544+
1545+
if (settings.CanLogin.has_value()) {
1546+
alterUser.SetCanLogin(settings.CanLogin.value());
15381547
}
15391548

15401549
auto& phyQuery = *SessionCtx->Query().PreparingQuery->MutablePhysicalQuery();

ydb/core/kqp/provider/yql_kikimr_exec.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ namespace {
103103
TCreateUserSettings ParseCreateUserSettings(TKiCreateUser createUser) {
104104
TCreateUserSettings createUserSettings;
105105
createUserSettings.UserName = TString(createUser.UserName());
106+
createUserSettings.CanLogin = true;
106107

107108
for (auto setting : createUser.Settings()) {
108109
auto name = setting.Name().Value();
@@ -112,6 +113,10 @@ namespace {
112113
// Default value
113114
} else if (name == "passwordEncrypted") {
114115
createUserSettings.PasswordEncrypted = true;
116+
} else if (name == "login") {
117+
createUserSettings.CanLogin = true;
118+
} else if (name == "noLogin") {
119+
createUserSettings.CanLogin = false;
115120
}
116121
}
117122
return createUserSettings;
@@ -126,9 +131,13 @@ namespace {
126131
if (name == "password") {
127132
alterUserSettings.Password = setting.Value().Cast<TCoAtom>().StringValue();
128133
} else if (name == "nullPassword") {
129-
// Default value
134+
alterUserSettings.Password = TString();
130135
} else if (name == "passwordEncrypted") {
131136
alterUserSettings.PasswordEncrypted = true;
137+
} else if (name == "login") {
138+
alterUserSettings.CanLogin = true;
139+
} else if (name == "noLogin") {
140+
alterUserSettings.CanLogin = false;
132141
}
133142
}
134143
return alterUserSettings;

ydb/core/kqp/provider/yql_kikimr_gateway.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ struct TCreateUserSettings {
662662
TString UserName;
663663
TString Password;
664664
bool PasswordEncrypted = false;
665+
bool CanLogin;
665666
};
666667

667668
struct TModifyPermissionsSettings {
@@ -679,8 +680,9 @@ struct TModifyPermissionsSettings {
679680

680681
struct TAlterUserSettings {
681682
TString UserName;
682-
TString Password;
683+
std::optional<TString> Password;
683684
bool PasswordEncrypted = false;
685+
std::optional<bool> CanLogin;
684686
};
685687

686688
struct TDropUserSettings {

ydb/core/kqp/provider/yql_kikimr_type_ann.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,8 +1830,23 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
18301830
}
18311831

18321832
virtual TStatus HandleCreateUser(TKiCreateUser node, TExprContext& ctx) override {
1833+
const THashSet<TString> supportedSettings = {
1834+
"password",
1835+
"passwordEncrypted",
1836+
"nullPassword",
1837+
"login",
1838+
"noLogin"
1839+
};
1840+
18331841
for (const auto& setting : node.Settings()) {
18341842
auto name = setting.Name().Value();
1843+
1844+
if (!supportedSettings.contains(name)) {
1845+
ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()),
1846+
TStringBuilder() << "Unknown create user setting: " << name));
1847+
return TStatus::Error;
1848+
}
1849+
18351850
if (name == "password") {
18361851
if (!EnsureAtom(setting.Value().Ref(), ctx)) {
18371852
return TStatus::Error;
@@ -1846,10 +1861,6 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
18461861
ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()),
18471862
TStringBuilder() << "nullPassword node shouldn't have value" << name));
18481863
}
1849-
} else {
1850-
ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()),
1851-
TStringBuilder() << "Unknown create user setting: " << name));
1852-
return TStatus::Error;
18531864
}
18541865
}
18551866

@@ -1858,8 +1869,23 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
18581869
}
18591870

18601871
virtual TStatus HandleAlterUser(TKiAlterUser node, TExprContext& ctx) override {
1872+
const THashSet<TString> supportedSettings = {
1873+
"password",
1874+
"passwordEncrypted",
1875+
"nullPassword",
1876+
"login",
1877+
"noLogin"
1878+
};
1879+
18611880
for (const auto& setting : node.Settings()) {
18621881
auto name = setting.Name().Value();
1882+
1883+
if (!supportedSettings.contains(name)) {
1884+
ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()),
1885+
TStringBuilder() << "Unknown alter user setting: " << name));
1886+
return TStatus::Error;
1887+
}
1888+
18631889
if (name == "password") {
18641890
if (!EnsureAtom(setting.Value().Ref(), ctx)) {
18651891
return TStatus::Error;
@@ -1874,10 +1900,6 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
18741900
ctx.AddError(TIssue(ctx.GetPosition(setting.Value().Ref().Pos()),
18751901
TStringBuilder() << "nullPassword node shouldn't have value" << name));
18761902
}
1877-
} else {
1878-
ctx.AddError(TIssue(ctx.GetPosition(setting.Name().Pos()),
1879-
TStringBuilder() << "Unknown alter user setting: " << name));
1880-
return TStatus::Error;
18811903
}
18821904
}
18831905

ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3366,6 +3366,75 @@ Y_UNIT_TEST_SUITE(KqpScheme) {
33663366
}
33673367
}
33683368

3369+
Y_UNIT_TEST(CreateAlterUserLoginNoLogin) {
3370+
TKikimrRunner kikimr;
3371+
auto db = kikimr.GetTableClient();
3372+
{
3373+
auto query = TStringBuilder() << R"(
3374+
--!syntax_v1
3375+
CREATE USER user1 ENCRYPTED PASSWORD '123' LOGIN;
3376+
)";
3377+
auto session = db.CreateSession().GetValueSync().GetSession();
3378+
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
3379+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
3380+
}
3381+
3382+
{
3383+
auto query = TStringBuilder() << R"(
3384+
--!syntax_v1
3385+
CREATE USER user2 ENCRYPTED PASSWORD '123' NOLOGIN;
3386+
)";
3387+
auto session = db.CreateSession().GetValueSync().GetSession();
3388+
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
3389+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
3390+
}
3391+
3392+
{
3393+
auto query = TStringBuilder() << R"(
3394+
--!syntax_v1
3395+
CREATE USER user3 ENCRYPTED PASSWORD '123';
3396+
ALTER USER user3 NOLOGIN;
3397+
)";
3398+
auto session = db.CreateSession().GetValueSync().GetSession();
3399+
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
3400+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
3401+
}
3402+
3403+
{
3404+
auto query = TStringBuilder() << R"(
3405+
--!syntax_v1
3406+
CREATE USER user4 ENCRYPTED PASSWORD '123' NOLOGIN;
3407+
ALTER USER user4 LOGIN;
3408+
)";
3409+
auto session = db.CreateSession().GetValueSync().GetSession();
3410+
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
3411+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
3412+
}
3413+
3414+
{
3415+
auto query = TStringBuilder() << R"(
3416+
--!syntax_v1
3417+
CREATE USER user5 someNonExistentOption;
3418+
)";
3419+
auto session = db.CreateSession().GetValueSync().GetSession();
3420+
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
3421+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString());
3422+
UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Unexpected token \'someNonExistentOption\'");
3423+
}
3424+
3425+
{
3426+
auto query = TStringBuilder() << R"(
3427+
--!syntax_v1
3428+
CREATE USER user6;
3429+
ALTER USER user6 someNonExistentOption;
3430+
)";
3431+
auto session = db.CreateSession().GetValueSync().GetSession();
3432+
auto result = session.ExecuteSchemeQuery(query).GetValueSync();
3433+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString());
3434+
UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Unexpected token \'someNonExistentOption\'");
3435+
}
3436+
}
3437+
33693438
struct ExpectedPermissions {
33703439
TString Path;
33713440
THashMap<TString, TVector<TString>> Permissions;

ydb/core/protos/flat_scheme_op.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,11 +848,13 @@ message TReshardColumnTable {
848848
message TLoginCreateUser {
849849
optional string User = 1;
850850
optional string Password = 2;
851+
optional bool CanLogin = 3 [default = true];
851852
}
852853

853854
message TLoginModifyUser {
854855
optional string User = 1;
855856
optional string Password = 2;
857+
optional bool CanLogin = 3;
856858
}
857859

858860
message TLoginRemoveUser {

ydb/core/testlib/test_client.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,16 +2031,16 @@ namespace Tests {
20312031
return (NMsgBusProxy::EResponseStatus)response.GetStatus();
20322032
}
20332033

2034-
NMsgBusProxy::EResponseStatus TClient::CreateUser(const TString& parent, const TString& user, const TString& password, const TString& userToken) {
2034+
NMsgBusProxy::EResponseStatus TClient::CreateUser(const TString& parent, const TCreateUserOption& options, const TString& userToken) {
20352035
TAutoPtr<NMsgBusProxy::TBusSchemeOperation> request(new NMsgBusProxy::TBusSchemeOperation());
20362036
auto* op = request->Record.MutableTransaction()->MutableModifyScheme();
20372037
op->SetOperationType(NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin);
20382038
op->SetWorkingDir(parent);
20392039

20402040
auto* createUser = op->MutableAlterLogin()->MutableCreateUser();
2041-
createUser->SetUser(user);
2042-
createUser->SetPassword(password);
2043-
2041+
createUser->SetUser(options.User);
2042+
createUser->SetPassword(options.Password);
2043+
createUser->SetCanLogin(options.CanLogin);
20442044
request->Record.SetSecurityToken(userToken);
20452045

20462046
TAutoPtr<NBus::TBusMessage> reply;
@@ -2051,7 +2051,11 @@ namespace Tests {
20512051
return (NMsgBusProxy::EResponseStatus)response.GetStatus();
20522052
}
20532053

2054-
NMsgBusProxy::EResponseStatus TClient::ModifyUser(const TString& parent, const TString& user, const TString& password, const TString& userToken) {
2054+
NMsgBusProxy::EResponseStatus TClient::CreateUser(const TString& parent, const TString& user, const TString& password, const TString& userToken) {
2055+
return CreateUser(parent, {.User = user, .Password = password}, userToken);
2056+
}
2057+
2058+
NMsgBusProxy::EResponseStatus TClient::ModifyUser(const TString& parent, const TModifyUserOption& options, const TString& userToken) {
20552059
TAutoPtr<NMsgBusProxy::TBusSchemeOperation> request(new NMsgBusProxy::TBusSchemeOperation());
20562060
auto* op = request->Record.MutableTransaction()->MutableModifyScheme();
20572061
op->SetOperationType(NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin);
@@ -2060,8 +2064,15 @@ namespace Tests {
20602064
request->Record.SetSecurityToken(userToken);
20612065

20622066
auto* modifyUser = op->MutableAlterLogin()->MutableModifyUser();
2063-
modifyUser->SetUser(user);
2064-
modifyUser->SetPassword(password);
2067+
modifyUser->SetUser(options.User);
2068+
2069+
if (options.Password.has_value()) {
2070+
modifyUser->SetPassword(options.Password.value());
2071+
}
2072+
2073+
if (options.CanLogin.has_value()) {
2074+
modifyUser->SetCanLogin(options.CanLogin.value());
2075+
}
20652076

20662077
TAutoPtr<NBus::TBusMessage> reply;
20672078
NBus::EMessageStatus status = SendAndWaitCompletion(request.Release(), reply);

ydb/core/testlib/test_client.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,19 @@ namespace Tests {
380380
ui64 PathId = 0;
381381
ui64 Version = 0;
382382
};
383+
384+
struct TCreateUserOption {
385+
TString User;
386+
TString Password;
387+
bool CanLogin = true;
388+
};
389+
390+
struct TModifyUserOption {
391+
TString User;
392+
std::optional<TString> Password;
393+
std::optional<bool> CanLogin;
394+
};
395+
383396
using TApplyIf = TVector<TPathVersion>;
384397

385398
TClient(const TServerSettings& settings);
@@ -460,8 +473,9 @@ namespace Tests {
460473
NMsgBusProxy::EResponseStatus DeleteSubdomain(const TString& parent, const TString &name);
461474
NMsgBusProxy::EResponseStatus ForceDeleteSubdomain(const TString& parent, const TString &name);
462475
NMsgBusProxy::EResponseStatus ForceDeleteUnsafe(const TString& parent, const TString &name);
476+
NMsgBusProxy::EResponseStatus CreateUser(const TString& parent, const TCreateUserOption& options, const TString& userToken = "");
463477
NMsgBusProxy::EResponseStatus CreateUser(const TString& parent, const TString& user, const TString& password, const TString& userToken = "");
464-
NMsgBusProxy::EResponseStatus ModifyUser(const TString& parent, const TString& user, const TString& password, const TString& userToken = "");
478+
NMsgBusProxy::EResponseStatus ModifyUser(const TString& parent, const TModifyUserOption& options, const TString& userToken = "");
465479
NKikimrScheme::TEvLoginResult Login(TTestActorRuntime& runtime, const TString& user, const TString& password);
466480
NMsgBusProxy::EResponseStatus CreateGroup(const TString& parent, const TString& group);
467481
NMsgBusProxy::EResponseStatus AddGroupMembership(const TString& parent, const TString& group, const TString& member);

ydb/core/tx/schemeshard/schemeshard__init.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,6 +3887,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
38873887
sid.SetFailedLoginAttemptCount(rowset.GetValueOrDefault<Schema::LoginSids::FailedAttemptCount>());
38883888
sid.SetLastFailedLogin(rowset.GetValueOrDefault<Schema::LoginSids::LastFailedAttempt>());
38893889
sid.SetLastSuccessfulLogin(rowset.GetValueOrDefault<Schema::LoginSids::LastSuccessfulAttempt>());
3890+
sid.SetIsEnabled(rowset.GetValueOrDefault<Schema::LoginSids::IsEnabled>());
38903891
sidIndex[sid.name()] = securityState.SidsSize() - 1;
38913892
if (!rowset.Next()) {
38923893
return false;

ydb/core/tx/schemeshard/schemeshard__login.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
1313
TPathId SubDomainPathId;
1414
bool NeedPublishOnComplete = false;
1515
THolder<TEvSchemeShard::TEvLoginResult> Result = MakeHolder<TEvSchemeShard::TEvLoginResult>();
16-
size_t CurrentFailedAttemptCount = 0;
1716

1817
TTxLogin(TSelf *self, TEvSchemeShard::TEvLogin::TPtr &ev)
1918
: TRwTxBase(self)
@@ -173,9 +172,9 @@ struct TSchemeShard::TTxLogin : TSchemeShard::TRwTxBase {
173172
Result->Record.SetError(loginResponse.Error);
174173
break;
175174
}
176-
case TLoginProvider::TLoginUserResponse::EStatus::INVALID_USER:
177-
case TLoginProvider::TLoginUserResponse::EStatus::UNAVAILABLE_KEY:
178-
case TLoginProvider::TLoginUserResponse::EStatus::UNSPECIFIED: {
175+
case NLogin::TLoginProvider::TLoginUserResponse::EStatus::INVALID_USER:
176+
case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNAVAILABLE_KEY:
177+
case NLogin::TLoginProvider::TLoginUserResponse::EStatus::UNSPECIFIED: {
179178
Result->Record.SetError(loginResponse.Error);
180179
break;
181180
}

0 commit comments

Comments
 (0)