github.com/cyverse/go-irodsclient@v0.13.2/irods/fs/usergroup.go (about) 1 package fs 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "github.com/cyverse/go-irodsclient/irods/common" 8 "github.com/cyverse/go-irodsclient/irods/connection" 9 "github.com/cyverse/go-irodsclient/irods/message" 10 "github.com/cyverse/go-irodsclient/irods/types" 11 "github.com/cyverse/go-irodsclient/irods/util" 12 "golang.org/x/xerrors" 13 ) 14 15 // GetGroup returns the group 16 func GetGroup(conn *connection.IRODSConnection, group string) (*types.IRODSUser, error) { 17 if conn == nil || !conn.IsConnected() { 18 return nil, xerrors.Errorf("connection is nil or disconnected") 19 } 20 21 // lock the connection 22 conn.Lock() 23 defer conn.Unlock() 24 25 users := []*types.IRODSUser{} 26 27 continueQuery := true 28 continueIndex := 0 29 for continueQuery { 30 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 31 query.AddSelect(common.ICAT_COLUMN_USER_ID, 1) 32 query.AddSelect(common.ICAT_COLUMN_USER_NAME, 1) 33 query.AddSelect(common.ICAT_COLUMN_USER_TYPE, 1) 34 query.AddSelect(common.ICAT_COLUMN_USER_ZONE, 1) 35 36 condNameVal := fmt.Sprintf("= '%s'", group) 37 query.AddCondition(common.ICAT_COLUMN_USER_NAME, condNameVal) 38 condTypeVal := fmt.Sprintf("= '%s'", types.IRODSUserRodsGroup) 39 query.AddCondition(common.ICAT_COLUMN_USER_TYPE, condTypeVal) 40 41 queryResult := message.IRODSMessageQueryResponse{} 42 err := conn.Request(query, &queryResult, nil) 43 if err != nil { 44 return nil, xerrors.Errorf("failed to receive a group query result message: %w", err) 45 } 46 47 err = queryResult.CheckError() 48 if err != nil { 49 return nil, xerrors.Errorf("received a group query error: %w", err) 50 } 51 52 if queryResult.RowCount == 0 { 53 break 54 } 55 56 if queryResult.AttributeCount > len(queryResult.SQLResult) { 57 return nil, xerrors.Errorf("failed to receive group attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 58 } 59 60 pagenatedUsers := make([]*types.IRODSUser, queryResult.RowCount) 61 62 for attr := 0; attr < queryResult.AttributeCount; attr++ { 63 sqlResult := queryResult.SQLResult[attr] 64 if len(sqlResult.Values) != queryResult.RowCount { 65 return nil, xerrors.Errorf("failed to receive group rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 66 } 67 68 for row := 0; row < queryResult.RowCount; row++ { 69 value := sqlResult.Values[row] 70 71 if pagenatedUsers[row] == nil { 72 // create a new 73 pagenatedUsers[row] = &types.IRODSUser{ 74 ID: -1, 75 Zone: "", 76 Name: "", 77 Type: types.IRODSUserRodsUser, 78 } 79 } 80 81 switch sqlResult.AttributeIndex { 82 case int(common.ICAT_COLUMN_USER_ID): 83 userID, err := strconv.ParseInt(value, 10, 64) 84 if err != nil { 85 return nil, xerrors.Errorf("failed to parse user id '%s': %w", value, err) 86 } 87 pagenatedUsers[row].ID = userID 88 case int(common.ICAT_COLUMN_USER_ZONE): 89 pagenatedUsers[row].Zone = value 90 case int(common.ICAT_COLUMN_USER_NAME): 91 pagenatedUsers[row].Name = value 92 case int(common.ICAT_COLUMN_USER_TYPE): 93 pagenatedUsers[row].Type = types.IRODSUserType(value) 94 default: 95 // ignore 96 } 97 } 98 } 99 100 users = append(users, pagenatedUsers...) 101 102 continueIndex = queryResult.ContinueIndex 103 if continueIndex == 0 { 104 continueQuery = false 105 } 106 } 107 108 if len(users) == 0 { 109 return nil, xerrors.Errorf("failed to find the group for name %s: %w", group, types.NewUserNotFoundError(group)) 110 } 111 112 return users[0], nil 113 } 114 115 // ListGroupUsers returns users in the group 116 func ListGroupUsers(conn *connection.IRODSConnection, group string) ([]*types.IRODSUser, error) { 117 if conn == nil || !conn.IsConnected() { 118 return nil, xerrors.Errorf("connection is nil or disconnected") 119 } 120 121 // lock the connection 122 conn.Lock() 123 defer conn.Unlock() 124 125 users := []*types.IRODSUser{} 126 127 continueQuery := true 128 continueIndex := 0 129 for continueQuery { 130 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 131 query.AddSelect(common.ICAT_COLUMN_USER_ID, 1) 132 query.AddSelect(common.ICAT_COLUMN_USER_NAME, 1) 133 query.AddSelect(common.ICAT_COLUMN_USER_TYPE, 1) 134 query.AddSelect(common.ICAT_COLUMN_USER_ZONE, 1) 135 136 condNameVal := fmt.Sprintf("= '%s'", group) 137 query.AddCondition(common.ICAT_COLUMN_COLL_USER_GROUP_NAME, condNameVal) 138 139 queryResult := message.IRODSMessageQueryResponse{} 140 err := conn.Request(query, &queryResult, nil) 141 if err != nil { 142 return nil, xerrors.Errorf("failed to receive a group user query result message: %w", err) 143 } 144 145 err = queryResult.CheckError() 146 if err != nil { 147 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 148 // empty 149 break 150 } 151 return nil, xerrors.Errorf("received a group user query error: %w", err) 152 } 153 154 if queryResult.RowCount == 0 { 155 break 156 } 157 158 if queryResult.AttributeCount > len(queryResult.SQLResult) { 159 return nil, xerrors.Errorf("failed to receive group user attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 160 } 161 162 pagenatedUsers := make([]*types.IRODSUser, queryResult.RowCount) 163 164 for attr := 0; attr < queryResult.AttributeCount; attr++ { 165 sqlResult := queryResult.SQLResult[attr] 166 if len(sqlResult.Values) != queryResult.RowCount { 167 return nil, xerrors.Errorf("failed to receive group user rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 168 } 169 170 for row := 0; row < queryResult.RowCount; row++ { 171 value := sqlResult.Values[row] 172 173 if pagenatedUsers[row] == nil { 174 // create a new 175 pagenatedUsers[row] = &types.IRODSUser{ 176 ID: -1, 177 Zone: "", 178 Name: "", 179 Type: types.IRODSUserRodsUser, 180 } 181 } 182 183 switch sqlResult.AttributeIndex { 184 case int(common.ICAT_COLUMN_USER_ID): 185 userID, err := strconv.ParseInt(value, 10, 64) 186 if err != nil { 187 return nil, xerrors.Errorf("failed to parse user id '%s': %w", value, err) 188 } 189 pagenatedUsers[row].ID = userID 190 case int(common.ICAT_COLUMN_USER_ZONE): 191 pagenatedUsers[row].Zone = value 192 case int(common.ICAT_COLUMN_USER_NAME): 193 pagenatedUsers[row].Name = value 194 case int(common.ICAT_COLUMN_USER_TYPE): 195 pagenatedUsers[row].Type = types.IRODSUserType(value) 196 default: 197 // ignore 198 } 199 } 200 } 201 202 users = append(users, pagenatedUsers...) 203 204 continueIndex = queryResult.ContinueIndex 205 if continueIndex == 0 { 206 continueQuery = false 207 } 208 } 209 210 return users, nil 211 } 212 213 // ListGroups returns all groups 214 func ListGroups(conn *connection.IRODSConnection) ([]*types.IRODSUser, error) { 215 if conn == nil || !conn.IsConnected() { 216 return nil, xerrors.Errorf("connection is nil or disconnected") 217 } 218 219 // lock the connection 220 conn.Lock() 221 defer conn.Unlock() 222 223 groups := []*types.IRODSUser{} 224 225 continueQuery := true 226 continueIndex := 0 227 for continueQuery { 228 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 229 query.AddSelect(common.ICAT_COLUMN_USER_ID, 1) 230 query.AddSelect(common.ICAT_COLUMN_USER_NAME, 1) 231 query.AddSelect(common.ICAT_COLUMN_USER_TYPE, 1) 232 query.AddSelect(common.ICAT_COLUMN_USER_ZONE, 1) 233 234 condTypeVal := fmt.Sprintf("= '%s'", types.IRODSUserRodsGroup) 235 query.AddCondition(common.ICAT_COLUMN_USER_TYPE, condTypeVal) 236 237 queryResult := message.IRODSMessageQueryResponse{} 238 err := conn.Request(query, &queryResult, nil) 239 if err != nil { 240 return nil, xerrors.Errorf("failed to receive a group query result message: %w", err) 241 } 242 243 err = queryResult.CheckError() 244 if err != nil { 245 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 246 // empty 247 break 248 } 249 return nil, xerrors.Errorf("received a group query error: %w", err) 250 } 251 252 if queryResult.RowCount == 0 { 253 break 254 } 255 256 if queryResult.AttributeCount > len(queryResult.SQLResult) { 257 return nil, xerrors.Errorf("failed to receive group attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 258 } 259 260 pagenatedGroups := make([]*types.IRODSUser, queryResult.RowCount) 261 262 for attr := 0; attr < queryResult.AttributeCount; attr++ { 263 sqlResult := queryResult.SQLResult[attr] 264 if len(sqlResult.Values) != queryResult.RowCount { 265 return nil, xerrors.Errorf("failed to receive group rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 266 } 267 268 for row := 0; row < queryResult.RowCount; row++ { 269 value := sqlResult.Values[row] 270 271 if pagenatedGroups[row] == nil { 272 // create a new 273 pagenatedGroups[row] = &types.IRODSUser{ 274 ID: -1, 275 Zone: "", 276 Name: "", 277 Type: types.IRODSUserRodsUser, 278 } 279 } 280 281 switch sqlResult.AttributeIndex { 282 case int(common.ICAT_COLUMN_USER_ID): 283 userID, err := strconv.ParseInt(value, 10, 64) 284 if err != nil { 285 return nil, xerrors.Errorf("failed to parse user id '%s': %w", value, err) 286 } 287 pagenatedGroups[row].ID = userID 288 case int(common.ICAT_COLUMN_USER_ZONE): 289 pagenatedGroups[row].Zone = value 290 case int(common.ICAT_COLUMN_USER_NAME): 291 pagenatedGroups[row].Name = value 292 case int(common.ICAT_COLUMN_USER_TYPE): 293 pagenatedGroups[row].Type = types.IRODSUserType(value) 294 default: 295 // ignore 296 } 297 } 298 } 299 300 groups = append(groups, pagenatedGroups...) 301 302 continueIndex = queryResult.ContinueIndex 303 if continueIndex == 0 { 304 continueQuery = false 305 } 306 } 307 308 return groups, nil 309 } 310 311 // ListUsers lists all users 312 func ListUsers(conn *connection.IRODSConnection) ([]*types.IRODSUser, error) { 313 if conn == nil || !conn.IsConnected() { 314 return nil, xerrors.Errorf("connection is nil or disconnected") 315 } 316 317 // lock the connection 318 conn.Lock() 319 defer conn.Unlock() 320 321 users := []*types.IRODSUser{} 322 323 continueQuery := true 324 continueIndex := 0 325 for continueQuery { 326 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 327 query.AddSelect(common.ICAT_COLUMN_USER_ID, 1) 328 query.AddSelect(common.ICAT_COLUMN_USER_NAME, 1) 329 query.AddSelect(common.ICAT_COLUMN_USER_TYPE, 1) 330 query.AddSelect(common.ICAT_COLUMN_USER_ZONE, 1) 331 332 condTypeVal := fmt.Sprintf("<> '%s'", types.IRODSUserRodsGroup) 333 query.AddCondition(common.ICAT_COLUMN_USER_TYPE, condTypeVal) 334 335 queryResult := message.IRODSMessageQueryResponse{} 336 err := conn.Request(query, &queryResult, nil) 337 if err != nil { 338 return nil, xerrors.Errorf("failed to receive a user query result message: %w", err) 339 } 340 341 err = queryResult.CheckError() 342 if err != nil { 343 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 344 // empty 345 break 346 } 347 return nil, xerrors.Errorf("received a user query error: %w", err) 348 } 349 350 if queryResult.RowCount == 0 { 351 break 352 } 353 354 if queryResult.AttributeCount > len(queryResult.SQLResult) { 355 return nil, xerrors.Errorf("failed to receive user attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 356 } 357 358 pagenatedUsers := make([]*types.IRODSUser, queryResult.RowCount) 359 360 for attr := 0; attr < queryResult.AttributeCount; attr++ { 361 sqlResult := queryResult.SQLResult[attr] 362 if len(sqlResult.Values) != queryResult.RowCount { 363 return nil, xerrors.Errorf("failed to receive user rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 364 } 365 366 for row := 0; row < queryResult.RowCount; row++ { 367 value := sqlResult.Values[row] 368 369 if pagenatedUsers[row] == nil { 370 // create a new 371 pagenatedUsers[row] = &types.IRODSUser{ 372 ID: -1, 373 Zone: "", 374 Name: "", 375 Type: types.IRODSUserRodsUser, 376 } 377 } 378 379 switch sqlResult.AttributeIndex { 380 case int(common.ICAT_COLUMN_USER_ID): 381 userID, err := strconv.ParseInt(value, 10, 64) 382 if err != nil { 383 return nil, xerrors.Errorf("failed to parse user id '%s': %w", value, err) 384 } 385 pagenatedUsers[row].ID = userID 386 case int(common.ICAT_COLUMN_USER_ZONE): 387 pagenatedUsers[row].Zone = value 388 case int(common.ICAT_COLUMN_USER_NAME): 389 pagenatedUsers[row].Name = value 390 case int(common.ICAT_COLUMN_USER_TYPE): 391 pagenatedUsers[row].Type = types.IRODSUserType(value) 392 default: 393 // ignore 394 } 395 } 396 } 397 398 users = append(users, pagenatedUsers...) 399 400 continueIndex = queryResult.ContinueIndex 401 if continueIndex == 0 { 402 continueQuery = false 403 } 404 } 405 406 return users, nil 407 } 408 409 // ListUserGroupNames lists the group names a user is a member of 410 func ListUserGroupNames(conn *connection.IRODSConnection, user string) ([]string, error) { 411 if conn == nil || !conn.IsConnected() { 412 return nil, xerrors.Errorf("connection is nil or disconnected") 413 } 414 415 // lock the connection 416 conn.Lock() 417 defer conn.Unlock() 418 419 var groups []string 420 421 continueQuery := true 422 continueIndex := 0 423 for continueQuery { 424 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 425 query.AddSelect(common.ICAT_COLUMN_COLL_USER_GROUP_NAME, 1) 426 427 condTypeVal := fmt.Sprintf("= '%s'", user) 428 query.AddCondition(common.ICAT_COLUMN_USER_NAME, condTypeVal) 429 430 queryResult := message.IRODSMessageQueryResponse{} 431 err := conn.Request(query, &queryResult, nil) 432 if err != nil { 433 return nil, xerrors.Errorf("failed to receive a group query result message: %w", err) 434 } 435 436 err = queryResult.CheckError() 437 if err != nil { 438 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 439 // empty 440 break 441 } 442 return nil, xerrors.Errorf("received a group query error: %w", err) 443 } 444 445 if queryResult.RowCount == 0 { 446 break 447 } 448 449 if queryResult.AttributeCount > len(queryResult.SQLResult) { 450 return nil, xerrors.Errorf("failed to receive group attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 451 } 452 453 var groupNames []string 454 455 for attr := 0; attr < queryResult.AttributeCount; attr++ { 456 sqlResult := queryResult.SQLResult[attr] 457 if len(sqlResult.Values) != queryResult.RowCount { 458 return nil, xerrors.Errorf("failed to receive group rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 459 } 460 461 for row := 0; row < queryResult.RowCount; row++ { 462 value := sqlResult.Values[row] 463 464 if value != user { 465 groupNames = append(groupNames, value) 466 } 467 468 } 469 } 470 471 groups = append(groups, groupNames...) 472 473 continueIndex = queryResult.ContinueIndex 474 if continueIndex == 0 { 475 continueQuery = false 476 } 477 } 478 479 return groups, nil 480 } 481 482 // CreateUser creates a user. 483 func CreateUser(conn *connection.IRODSConnection, username string, zone string, userType string) error { 484 // lock the connection 485 conn.Lock() 486 defer conn.Unlock() 487 488 userZoneName := fmt.Sprintf("%s#%s", username, zone) 489 490 req := message.NewIRODSMessageAdminRequest("add", "user", userZoneName, userType, zone) 491 492 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 493 if err != nil { 494 return xerrors.Errorf("received create user error: %w", err) 495 } 496 return nil 497 } 498 499 // ChangeUserPassword changes the password of a user object 500 func ChangeUserPassword(conn *connection.IRODSConnection, username string, zone string, newPassword string) error { 501 // lock the connection 502 conn.Lock() 503 defer conn.Unlock() 504 505 userZoneName := fmt.Sprintf("%s#%s", username, zone) 506 507 account := conn.GetAccount() 508 509 oldPassword := account.Password 510 if account.AuthenticationScheme == types.AuthSchemePAM { 511 oldPassword = conn.GetGeneratedPasswordForPAMAuth() 512 } 513 514 scrambledPassword := util.ObfuscateNewPassword(newPassword, oldPassword, conn.GetClientSignature()) 515 516 req := message.NewIRODSMessageAdminRequest("modify", "user", userZoneName, "password", scrambledPassword, zone) 517 518 err := conn.RequestAndCheckForPassword(req, &message.IRODSMessageAdminResponse{}, nil) 519 if err != nil { 520 return xerrors.Errorf("received change user password error: %w", err) 521 } 522 return nil 523 } 524 525 // ChangeUserType changes the type / role of a user object 526 func ChangeUserType(conn *connection.IRODSConnection, username string, zone string, newType string) error { 527 // lock the connection 528 conn.Lock() 529 defer conn.Unlock() 530 531 userZoneName := fmt.Sprintf("%s#%s", username, zone) 532 533 req := message.NewIRODSMessageAdminRequest("modify", "user", userZoneName, "type", newType, zone) 534 535 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 536 if err != nil { 537 return xerrors.Errorf("received change user type error: %w", err) 538 } 539 return nil 540 } 541 542 // RemoveUser removes a user or a group. 543 func RemoveUser(conn *connection.IRODSConnection, username string, zone string) error { 544 // lock the connection 545 conn.Lock() 546 defer conn.Unlock() 547 548 req := message.NewIRODSMessageAdminRequest("rm", "user", username, zone) 549 550 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 551 if err != nil { 552 return xerrors.Errorf("received remove user error: %w", err) 553 } 554 return nil 555 } 556 557 // CreateGroup creates a group. 558 func CreateGroup(conn *connection.IRODSConnection, groupname string, groupType string) error { 559 // lock the connection 560 conn.Lock() 561 defer conn.Unlock() 562 563 req := message.NewIRODSMessageAdminRequest("add", "user", groupname, groupType) 564 565 err := conn.RequestAndCheck(req, &message.IRODSMessageUserAdminResponse{}, nil) 566 if err != nil { 567 return xerrors.Errorf("received create group error: %w", err) 568 } 569 return nil 570 } 571 572 // AddGroupMember adds a user to a group. 573 func AddGroupMember(conn *connection.IRODSConnection, groupname string, username string, zone string) error { 574 // lock the connection 575 conn.Lock() 576 defer conn.Unlock() 577 578 req := message.NewIRODSMessageAdminRequest("modify", "group", groupname, "add", username, zone) 579 580 err := conn.RequestAndCheck(req, &message.IRODSMessageUserAdminResponse{}, nil) 581 if err != nil { 582 return xerrors.Errorf("received add group member error: %w", err) 583 } 584 return nil 585 } 586 587 // RemoveGroupMember removes a user from a group. 588 func RemoveGroupMember(conn *connection.IRODSConnection, groupname string, username string, zone string) error { 589 // lock the connection 590 conn.Lock() 591 defer conn.Unlock() 592 593 req := message.NewIRODSMessageAdminRequest("modify", "group", groupname, "remove", username, zone) 594 595 err := conn.RequestAndCheck(req, &message.IRODSMessageUserAdminResponse{}, nil) 596 if err != nil { 597 return xerrors.Errorf("received remove group member error: %w", err) 598 } 599 return nil 600 } 601 602 // ListUserResourceQuota lists all existing resource quota of a user or group 603 func ListUserResourceQuota(conn *connection.IRODSConnection, user string) ([]*types.IRODSQuota, error) { 604 if conn == nil || !conn.IsConnected() { 605 return nil, xerrors.Errorf("connection is nil or disconnected") 606 } 607 608 // lock the connection 609 conn.Lock() 610 defer conn.Unlock() 611 612 quota := []*types.IRODSQuota{} 613 614 continueQuery := true 615 continueIndex := 0 616 for continueQuery { 617 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 618 query.AddSelect(common.ICAT_COLUMN_QUOTA_RESC_NAME, 1) 619 query.AddSelect(common.ICAT_COLUMN_QUOTA_LIMIT, 1) 620 621 condTypeVal := fmt.Sprintf("= '%s'", user) 622 query.AddCondition(common.ICAT_COLUMN_QUOTA_USER_NAME, condTypeVal) 623 624 queryResult := message.IRODSMessageQueryResponse{} 625 err := conn.Request(query, &queryResult, nil) 626 if err != nil { 627 return nil, xerrors.Errorf("failed to receive a quota query result message: %w", err) 628 } 629 630 err = queryResult.CheckError() 631 if err != nil { 632 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 633 // empty 634 break 635 } 636 return nil, xerrors.Errorf("received a quota query error: %w", err) 637 } 638 639 if queryResult.RowCount == 0 { 640 break 641 } 642 643 if queryResult.AttributeCount > len(queryResult.SQLResult) { 644 return nil, xerrors.Errorf("failed to receive quota attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 645 } 646 647 pagenatedQuota := make([]*types.IRODSQuota, queryResult.RowCount) 648 649 for attr := 0; attr < queryResult.AttributeCount; attr++ { 650 sqlResult := queryResult.SQLResult[attr] 651 if len(sqlResult.Values) != queryResult.RowCount { 652 return nil, xerrors.Errorf("failed to receive quota rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 653 } 654 655 for row := 0; row < queryResult.RowCount; row++ { 656 value := sqlResult.Values[row] 657 658 if pagenatedQuota[row] == nil { 659 // create a new 660 pagenatedQuota[row] = &types.IRODSQuota{ 661 RescName: "", 662 Limit: -1, 663 } 664 } 665 666 switch sqlResult.AttributeIndex { 667 case int(common.ICAT_COLUMN_QUOTA_RESC_NAME): 668 pagenatedQuota[row].RescName = value 669 case int(common.ICAT_COLUMN_QUOTA_LIMIT): 670 limit, err := strconv.ParseInt(value, 10, 64) 671 if err != nil { 672 return nil, xerrors.Errorf("failed to parse quota limit '%s': %w", value, err) 673 } 674 pagenatedQuota[row].Limit = limit 675 default: 676 // ignore 677 } 678 } 679 } 680 681 quota = append(quota, pagenatedQuota...) 682 683 continueIndex = queryResult.ContinueIndex 684 if continueIndex == 0 { 685 continueQuery = false 686 } 687 } 688 689 return quota, nil 690 } 691 692 // GetUserGlobalQuota returns the global quota of a user or group 693 func GetUserGlobalQuota(conn *connection.IRODSConnection, user string) (*types.IRODSQuota, error) { 694 if conn == nil || !conn.IsConnected() { 695 return nil, xerrors.Errorf("connection is nil or disconnected") 696 } 697 698 // lock the connection 699 conn.Lock() 700 defer conn.Unlock() 701 702 quota := []*types.IRODSQuota{} 703 704 continueQuery := true 705 continueIndex := 0 706 for continueQuery { 707 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 708 query.AddSelect(common.ICAT_COLUMN_QUOTA_LIMIT, 1) 709 710 condTypeVal := fmt.Sprintf("= '%s'", user) 711 query.AddCondition(common.ICAT_COLUMN_QUOTA_USER_NAME, condTypeVal) 712 condTypeVal = fmt.Sprintf("= '%s'", "0") 713 query.AddCondition(common.ICAT_COLUMN_QUOTA_RESC_ID, condTypeVal) 714 715 queryResult := message.IRODSMessageQueryResponse{} 716 err := conn.Request(query, &queryResult, nil) 717 if err != nil { 718 return nil, xerrors.Errorf("failed to receive a quota query result message: %w", err) 719 } 720 721 err = queryResult.CheckError() 722 if err != nil { 723 return nil, xerrors.Errorf("received a quota query error: %w", err) 724 } 725 726 if queryResult.RowCount == 0 { 727 break 728 } 729 730 if queryResult.AttributeCount > len(queryResult.SQLResult) { 731 return nil, xerrors.Errorf("failed to receive quota attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 732 } 733 734 pagenatedQuota := make([]*types.IRODSQuota, queryResult.RowCount) 735 736 for attr := 0; attr < queryResult.AttributeCount; attr++ { 737 sqlResult := queryResult.SQLResult[attr] 738 if len(sqlResult.Values) != queryResult.RowCount { 739 return nil, xerrors.Errorf("failed to receive quota rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 740 } 741 742 for row := 0; row < queryResult.RowCount; row++ { 743 value := sqlResult.Values[row] 744 745 if pagenatedQuota[row] == nil { 746 // create a new 747 pagenatedQuota[row] = &types.IRODSQuota{ 748 RescName: "global", 749 Limit: -1, 750 } 751 } 752 753 switch sqlResult.AttributeIndex { 754 case int(common.ICAT_COLUMN_QUOTA_LIMIT): 755 limit, err := strconv.ParseInt(value, 10, 64) 756 if err != nil { 757 return nil, xerrors.Errorf("failed to parse quota limit '%s': %w", value, err) 758 } 759 pagenatedQuota[row].Limit = limit 760 default: 761 // ignore 762 } 763 } 764 } 765 766 quota = append(quota, pagenatedQuota...) 767 768 continueIndex = queryResult.ContinueIndex 769 if continueIndex == 0 { 770 continueQuery = false 771 } 772 } 773 774 return quota[0], nil 775 } 776 777 // AddUserMeta sets metadata of a user object to given key values. 778 func AddUserMeta(conn *connection.IRODSConnection, user string, metadata *types.IRODSMeta) error { 779 if conn == nil || !conn.IsConnected() { 780 return xerrors.Errorf("connection is nil or disconnected") 781 } 782 783 // lock the connection 784 conn.Lock() 785 defer conn.Unlock() 786 787 request := message.NewIRODSMessageAddMetadataRequest(types.IRODSUserMetaItemType, user, metadata) 788 response := message.IRODSMessageModifyMetadataResponse{} 789 return conn.RequestAndCheck(request, &response, nil) 790 } 791 792 // DeleteUserMeta removes the metadata of a user object. 793 // The metadata AVU is selected on basis of AVUID if it is supplied, otherwise on basis of Name, Value and Units. 794 func DeleteUserMeta(conn *connection.IRODSConnection, user string, metadata *types.IRODSMeta) error { 795 if conn == nil || !conn.IsConnected() { 796 return xerrors.Errorf("connection is nil or disconnected") 797 } 798 799 // lock the connection 800 conn.Lock() 801 defer conn.Unlock() 802 803 var request *message.IRODSMessageModifyMetadataRequest 804 805 if metadata.AVUID != 0 { 806 request = message.NewIRODSMessageRemoveMetadataByIDRequest(types.IRODSUserMetaItemType, user, metadata.AVUID) 807 } else if metadata.Units == "" && metadata.Value == "" { 808 request = message.NewIRODSMessageRemoveMetadataWildcardRequest(types.IRODSUserMetaItemType, user, metadata.Name) 809 } else { 810 request = message.NewIRODSMessageRemoveMetadataRequest(types.IRODSUserMetaItemType, user, metadata) 811 } 812 813 response := message.IRODSMessageModifyMetadataResponse{} 814 return conn.RequestAndCheck(request, &response, nil) 815 } 816 817 // ListUserMeta returns a user metadata for the path 818 func ListUserMeta(conn *connection.IRODSConnection, user string) ([]*types.IRODSMeta, error) { 819 if conn == nil || !conn.IsConnected() { 820 return nil, xerrors.Errorf("connection is nil or disconnected") 821 } 822 823 // lock the connection 824 conn.Lock() 825 defer conn.Unlock() 826 827 metas := []*types.IRODSMeta{} 828 829 continueQuery := true 830 continueIndex := 0 831 for continueQuery { 832 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 833 query.AddSelect(common.ICAT_COLUMN_META_USER_ATTR_ID, 1) 834 query.AddSelect(common.ICAT_COLUMN_META_USER_ATTR_NAME, 1) 835 query.AddSelect(common.ICAT_COLUMN_META_USER_ATTR_VALUE, 1) 836 query.AddSelect(common.ICAT_COLUMN_META_USER_ATTR_UNITS, 1) 837 838 nameCondVal := fmt.Sprintf("= '%s'", user) 839 query.AddCondition(common.ICAT_COLUMN_USER_NAME, nameCondVal) 840 841 queryResult := message.IRODSMessageQueryResponse{} 842 err := conn.Request(query, &queryResult, nil) 843 if err != nil { 844 return nil, xerrors.Errorf("failed to receive a user metadata query result message: %w", err) 845 } 846 847 err = queryResult.CheckError() 848 if err != nil { 849 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 850 // empty 851 break 852 } 853 return nil, xerrors.Errorf("received a user metadata query error: %w", err) 854 } 855 856 if queryResult.RowCount == 0 { 857 break 858 } 859 860 if queryResult.AttributeCount > len(queryResult.SQLResult) { 861 return nil, xerrors.Errorf("failed to receive user metadata attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 862 } 863 864 pagenatedMetas := make([]*types.IRODSMeta, queryResult.RowCount) 865 866 for attr := 0; attr < queryResult.AttributeCount; attr++ { 867 sqlResult := queryResult.SQLResult[attr] 868 if len(sqlResult.Values) != queryResult.RowCount { 869 return nil, xerrors.Errorf("failed to receive user metadata rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 870 } 871 872 for row := 0; row < queryResult.RowCount; row++ { 873 value := sqlResult.Values[row] 874 875 if pagenatedMetas[row] == nil { 876 // create a new 877 pagenatedMetas[row] = &types.IRODSMeta{ 878 AVUID: -1, 879 Name: "", 880 Value: "", 881 Units: "", 882 } 883 } 884 885 switch sqlResult.AttributeIndex { 886 case int(common.ICAT_COLUMN_META_USER_ATTR_ID): 887 avuID, err := strconv.ParseInt(value, 10, 64) 888 if err != nil { 889 return nil, xerrors.Errorf("failed to parse user metadata id '%s': %w", value, err) 890 } 891 pagenatedMetas[row].AVUID = avuID 892 case int(common.ICAT_COLUMN_META_USER_ATTR_NAME): 893 pagenatedMetas[row].Name = value 894 case int(common.ICAT_COLUMN_META_USER_ATTR_VALUE): 895 pagenatedMetas[row].Value = value 896 case int(common.ICAT_COLUMN_META_USER_ATTR_UNITS): 897 pagenatedMetas[row].Units = value 898 default: 899 // ignore 900 } 901 } 902 } 903 904 metas = append(metas, pagenatedMetas...) 905 906 continueIndex = queryResult.ContinueIndex 907 if continueIndex == 0 { 908 continueQuery = false 909 } 910 } 911 912 return metas, nil 913 } 914 915 // AddChildToResc adds a child to a parent resource 916 func AddChildToResc(conn *connection.IRODSConnection, parent string, child string, options string) error { 917 // lock the connection 918 conn.Lock() 919 defer conn.Unlock() 920 921 req := message.NewIRODSMessageAdminRequest("add", "childtoresc", parent, child, options) 922 923 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 924 if err != nil { 925 return xerrors.Errorf("received add child to resc error: %w", err) 926 } 927 return nil 928 } 929 930 // SetUserQuota sets quota for a given user and resource ('total' for global) 931 func SetUserQuota(conn *connection.IRODSConnection, user string, resource string, value string) error { 932 // lock the connection 933 conn.Lock() 934 defer conn.Unlock() 935 936 req := message.NewIRODSMessageAdminRequest("set-quota", "user", user, resource, value) 937 938 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 939 if err != nil { 940 return xerrors.Errorf("received set user quota error: %w", err) 941 } 942 return nil 943 } 944 945 // SetGroupQuota sets quota for a given user and resource ('total' for global) 946 func SetGroupQuota(conn *connection.IRODSConnection, group string, resource string, value string) error { 947 // lock the connection 948 conn.Lock() 949 defer conn.Unlock() 950 951 req := message.NewIRODSMessageAdminRequest("set-quota", "group", group, resource, value) 952 953 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 954 if err != nil { 955 return xerrors.Errorf("received set group quota error: %w", err) 956 } 957 return nil 958 }