github.com/cyverse/go-irodsclient@v0.13.2/irods/fs/ticket.go (about) 1 package fs 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "time" 8 9 "github.com/cyverse/go-irodsclient/irods/common" 10 "github.com/cyverse/go-irodsclient/irods/connection" 11 "github.com/cyverse/go-irodsclient/irods/message" 12 "github.com/cyverse/go-irodsclient/irods/types" 13 "github.com/cyverse/go-irodsclient/irods/util" 14 "github.com/rs/xid" 15 "golang.org/x/xerrors" 16 ) 17 18 // https://github.com/irods/irods_client_s3_ticketbooth/blob/b92e8aaa3127cb56fcb8fef09caa00244bd29ca6/ticket_booth/main.py 19 // GetTicketForAnonymousAccess returns minimal ticket information for the ticket name string 20 func GetTicketForAnonymousAccess(conn *connection.IRODSConnection, ticketName string) (*types.IRODSTicketForAnonymousAccess, error) { 21 if conn == nil || !conn.IsConnected() { 22 return nil, xerrors.Errorf("connection is nil or disconnected") 23 } 24 25 // lock the connection 26 conn.Lock() 27 defer conn.Unlock() 28 29 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, 0, 0, 0) 30 query.AddSelect(common.ICAT_COLUMN_TICKET_ID, 1) 31 query.AddSelect(common.ICAT_COLUMN_TICKET_TYPE, 1) 32 query.AddSelect(common.ICAT_COLUMN_TICKET_COLL_NAME, 1) 33 query.AddSelect(common.ICAT_COLUMN_TICKET_EXPIRY_TS, 1) 34 // We can't get common.ICAT_COLUMN_TICKET_STRING using query since it's not available for anonymous access 35 36 condVal := fmt.Sprintf("= '%s'", ticketName) 37 query.AddCondition(common.ICAT_COLUMN_TICKET_STRING, condVal) 38 39 queryResult := message.IRODSMessageQueryResponse{} 40 err := conn.Request(query, &queryResult, nil) 41 if err != nil { 42 return nil, xerrors.Errorf("failed to receive a ticket query result message: %w", err) 43 } 44 45 err = queryResult.CheckError() 46 if err != nil { 47 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 48 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 49 } 50 51 return nil, xerrors.Errorf("received a ticket query error: %w", err) 52 } 53 54 if queryResult.RowCount != 1 { 55 // file not found 56 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 57 } 58 59 if queryResult.AttributeCount > len(queryResult.SQLResult) { 60 return nil, xerrors.Errorf("failed to receive ticket attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 61 } 62 63 var ticketID int64 = -1 64 ticketType := types.TicketTypeRead 65 ticketPath := "" 66 expirationTime := time.Time{} 67 68 for idx := 0; idx < queryResult.AttributeCount; idx++ { 69 sqlResult := queryResult.SQLResult[idx] 70 if len(sqlResult.Values) != queryResult.RowCount { 71 return nil, xerrors.Errorf("failed to receive ticket rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 72 } 73 74 value := sqlResult.Values[0] 75 76 switch sqlResult.AttributeIndex { 77 case int(common.ICAT_COLUMN_TICKET_ID): 78 cID, err := strconv.ParseInt(value, 10, 64) 79 if err != nil { 80 return nil, xerrors.Errorf("failed to parse ticket id '%s': %w", value, err) 81 } 82 ticketID = cID 83 case int(common.ICAT_COLUMN_TICKET_TYPE): 84 ticketType = types.TicketType(value) 85 case int(common.ICAT_COLUMN_TICKET_COLL_NAME): 86 ticketPath = value 87 case int(common.ICAT_COLUMN_TICKET_EXPIRY_TS): 88 if len(strings.TrimSpace(value)) > 0 { 89 mT, err := util.GetIRODSDateTime(value) 90 if err != nil { 91 return nil, xerrors.Errorf("failed to parse expiry time '%s': %w", value, err) 92 } 93 expirationTime = mT 94 } 95 default: 96 // ignore 97 } 98 } 99 100 if ticketID == -1 { 101 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 102 } 103 104 return &types.IRODSTicketForAnonymousAccess{ 105 ID: ticketID, 106 Name: ticketName, 107 Type: ticketType, 108 Path: ticketPath, 109 ExpirationTime: expirationTime, 110 }, nil 111 } 112 113 // GetTicket returns the ticket 114 func GetTicket(conn *connection.IRODSConnection, ticketName string) (*types.IRODSTicket, error) { 115 if conn == nil || !conn.IsConnected() { 116 return nil, xerrors.Errorf("connection is nil or disconnected") 117 } 118 119 ticketColl, err := GetTicketForCollections(conn, ticketName) 120 if err != nil { 121 if !types.IsFileNotFoundError(err) { 122 return nil, err 123 } 124 } else { 125 if ticketColl != nil { 126 return ticketColl, nil 127 } 128 } 129 130 ticketsDataObj, err := GetTicketForDataObjects(conn, ticketName) 131 if err != nil { 132 if !types.IsFileNotFoundError(err) { 133 return nil, err 134 } 135 } else { 136 if ticketsDataObj != nil { 137 return ticketsDataObj, nil 138 } 139 } 140 141 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 142 } 143 144 // GetTicketForDataObjects returns ticket information for the ticket name string 145 func GetTicketForDataObjects(conn *connection.IRODSConnection, ticketName string) (*types.IRODSTicket, error) { 146 if conn == nil || !conn.IsConnected() { 147 return nil, xerrors.Errorf("connection is nil or disconnected") 148 } 149 150 // lock the connection 151 conn.Lock() 152 defer conn.Unlock() 153 154 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, 0, 0, 0) 155 query.AddSelect(common.ICAT_COLUMN_TICKET_ID, 1) 156 query.AddSelect(common.ICAT_COLUMN_TICKET_TYPE, 1) 157 query.AddSelect(common.ICAT_COLUMN_TICKET_OBJECT_TYPE, 1) 158 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_LIMIT, 1) 159 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_COUNT, 1) 160 query.AddSelect(common.ICAT_COLUMN_TICKET_EXPIRY_TS, 1) 161 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT, 1) 162 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT, 1) 163 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT, 1) 164 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT, 1) 165 query.AddSelect(common.ICAT_COLUMN_TICKET_DATA_NAME, 1) 166 query.AddSelect(common.ICAT_COLUMN_TICKET_DATA_COLL_NAME, 1) 167 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_NAME, 1) 168 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_ZONE, 1) 169 170 condVal := fmt.Sprintf("= '%s'", ticketName) 171 query.AddCondition(common.ICAT_COLUMN_TICKET_STRING, condVal) 172 173 queryResult := message.IRODSMessageQueryResponse{} 174 err := conn.Request(query, &queryResult, nil) 175 if err != nil { 176 return nil, xerrors.Errorf("failed to receive a ticket query result message: %w", err) 177 } 178 179 err = queryResult.CheckError() 180 if err != nil { 181 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 182 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 183 } 184 185 return nil, xerrors.Errorf("received a ticket query error: %w", err) 186 } 187 188 if queryResult.RowCount != 1 { 189 // file not found 190 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 191 } 192 193 if queryResult.AttributeCount > len(queryResult.SQLResult) { 194 return nil, xerrors.Errorf("failed to receive ticket attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 195 } 196 197 ticketID := int64(-1) 198 ticketType := types.TicketTypeRead 199 owner := "" 200 ownerZone := "" 201 objectType := types.ObjectTypeDataObject 202 ticketPath := "" 203 dataCollName := "" 204 dataName := "" 205 expirationTime := time.Time{} 206 usesLimit := int64(0) 207 usesCount := int64(0) 208 writeFileLimit := int64(0) 209 writeFileCount := int64(0) 210 writeByteLimit := int64(0) 211 writeByteCount := int64(0) 212 213 for idx := 0; idx < queryResult.AttributeCount; idx++ { 214 sqlResult := queryResult.SQLResult[idx] 215 if len(sqlResult.Values) != queryResult.RowCount { 216 return nil, xerrors.Errorf("failed to receive ticket rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 217 } 218 219 value := sqlResult.Values[0] 220 221 switch sqlResult.AttributeIndex { 222 case int(common.ICAT_COLUMN_TICKET_ID): 223 cID, err := strconv.ParseInt(value, 10, 64) 224 if err != nil { 225 return nil, xerrors.Errorf("failed to parse ticket id '%s': %w", value, err) 226 } 227 ticketID = cID 228 case int(common.ICAT_COLUMN_TICKET_TYPE): 229 ticketType = types.TicketType(value) 230 case int(common.ICAT_COLUMN_TICKET_OBJECT_TYPE): 231 objectType = types.ObjectType(value) 232 case int(common.ICAT_COLUMN_TICKET_USES_LIMIT): 233 limit, err := strconv.ParseInt(value, 10, 64) 234 if err != nil { 235 return nil, xerrors.Errorf("failed to parse uses limit '%s': %w", value, err) 236 } 237 usesLimit = limit 238 case int(common.ICAT_COLUMN_TICKET_USES_COUNT): 239 count, err := strconv.ParseInt(value, 10, 64) 240 if err != nil { 241 return nil, xerrors.Errorf("failed to parse uses count '%s': %w", value, err) 242 } 243 usesCount = count 244 case int(common.ICAT_COLUMN_TICKET_EXPIRY_TS): 245 if len(strings.TrimSpace(value)) > 0 { 246 mT, err := util.GetIRODSDateTime(value) 247 if err != nil { 248 return nil, xerrors.Errorf("failed to parse expiry time '%s': %w", value, err) 249 } 250 expirationTime = mT 251 } 252 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT): 253 limit, err := strconv.ParseInt(value, 10, 64) 254 if err != nil { 255 return nil, xerrors.Errorf("failed to parse write file limit '%s': %w", value, err) 256 } 257 writeFileLimit = limit 258 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT): 259 count, err := strconv.ParseInt(value, 10, 64) 260 if err != nil { 261 return nil, xerrors.Errorf("failed to parse write file count '%s': %w", value, err) 262 } 263 writeFileCount = count 264 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT): 265 limit, err := strconv.ParseInt(value, 10, 64) 266 if err != nil { 267 return nil, xerrors.Errorf("failed to parse write byte limit '%s': %w", value, err) 268 } 269 writeByteLimit = limit 270 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT): 271 count, err := strconv.ParseInt(value, 10, 64) 272 if err != nil { 273 return nil, xerrors.Errorf("failed to parse write byte count '%s': %w", value, err) 274 } 275 writeByteCount = count 276 case int(common.ICAT_COLUMN_TICKET_DATA_NAME): 277 dataName = value 278 ticketPath = util.MakeIRODSPath(dataCollName, value) 279 case int(common.ICAT_COLUMN_TICKET_DATA_COLL_NAME): 280 dataCollName = value 281 ticketPath = util.MakeIRODSPath(value, dataName) 282 case int(common.ICAT_COLUMN_TICKET_OWNER_NAME): 283 owner = value 284 case int(common.ICAT_COLUMN_TICKET_OWNER_ZONE): 285 ownerZone = value 286 default: 287 // ignore 288 } 289 } 290 291 if ticketID == -1 { 292 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 293 } 294 295 return &types.IRODSTicket{ 296 ID: ticketID, 297 Name: ticketName, 298 Type: ticketType, 299 Owner: owner, 300 OwnerZone: ownerZone, 301 ObjectType: objectType, 302 Path: ticketPath, 303 ExpirationTime: expirationTime, 304 UsesLimit: usesLimit, 305 UsesCount: usesCount, 306 WriteFileLimit: writeFileLimit, 307 WriteFileCount: writeFileCount, 308 WriteByteLimit: writeByteLimit, 309 WriteByteCount: writeByteCount, 310 }, nil 311 } 312 313 // GetTicketForCollections returns ticket information for the ticket name string 314 func GetTicketForCollections(conn *connection.IRODSConnection, ticketName string) (*types.IRODSTicket, error) { 315 if conn == nil || !conn.IsConnected() { 316 return nil, xerrors.Errorf("connection is nil or disconnected") 317 } 318 319 // lock the connection 320 conn.Lock() 321 defer conn.Unlock() 322 323 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, 0, 0, 0) 324 query.AddSelect(common.ICAT_COLUMN_TICKET_ID, 1) 325 query.AddSelect(common.ICAT_COLUMN_TICKET_TYPE, 1) 326 query.AddSelect(common.ICAT_COLUMN_TICKET_OBJECT_TYPE, 1) 327 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_LIMIT, 1) 328 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_COUNT, 1) 329 query.AddSelect(common.ICAT_COLUMN_TICKET_EXPIRY_TS, 1) 330 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT, 1) 331 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT, 1) 332 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT, 1) 333 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT, 1) 334 query.AddSelect(common.ICAT_COLUMN_TICKET_COLL_NAME, 1) 335 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_NAME, 1) 336 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_ZONE, 1) 337 338 condVal := fmt.Sprintf("= '%s'", ticketName) 339 query.AddCondition(common.ICAT_COLUMN_TICKET_STRING, condVal) 340 341 queryResult := message.IRODSMessageQueryResponse{} 342 err := conn.Request(query, &queryResult, nil) 343 if err != nil { 344 return nil, xerrors.Errorf("failed to receive a ticket query result message: %w", err) 345 } 346 347 err = queryResult.CheckError() 348 if err != nil { 349 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 350 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 351 } 352 353 return nil, xerrors.Errorf("received a ticket query error: %w", err) 354 } 355 356 if queryResult.RowCount != 1 { 357 // file not found 358 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 359 } 360 361 if queryResult.AttributeCount > len(queryResult.SQLResult) { 362 return nil, xerrors.Errorf("failed to receive ticket attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 363 } 364 365 ticketID := int64(-1) 366 ticketType := types.TicketTypeRead 367 owner := "" 368 ownerZone := "" 369 objectType := types.ObjectTypeCollection 370 ticketPath := "" 371 expirationTime := time.Time{} 372 usesLimit := int64(0) 373 usesCount := int64(0) 374 writeFileLimit := int64(0) 375 writeFileCount := int64(0) 376 writeByteLimit := int64(0) 377 writeByteCount := int64(0) 378 379 for idx := 0; idx < queryResult.AttributeCount; idx++ { 380 sqlResult := queryResult.SQLResult[idx] 381 if len(sqlResult.Values) != queryResult.RowCount { 382 return nil, xerrors.Errorf("failed to receive ticket rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 383 } 384 385 value := sqlResult.Values[0] 386 387 switch sqlResult.AttributeIndex { 388 case int(common.ICAT_COLUMN_TICKET_ID): 389 cID, err := strconv.ParseInt(value, 10, 64) 390 if err != nil { 391 return nil, xerrors.Errorf("failed to parse ticket id '%s': %w", value, err) 392 } 393 ticketID = cID 394 case int(common.ICAT_COLUMN_TICKET_TYPE): 395 ticketType = types.TicketType(value) 396 case int(common.ICAT_COLUMN_TICKET_OBJECT_TYPE): 397 objectType = types.ObjectType(value) 398 case int(common.ICAT_COLUMN_TICKET_USES_LIMIT): 399 limit, err := strconv.ParseInt(value, 10, 64) 400 if err != nil { 401 return nil, xerrors.Errorf("failed to parse uses limit '%s': %w", value, err) 402 } 403 usesLimit = limit 404 case int(common.ICAT_COLUMN_TICKET_USES_COUNT): 405 count, err := strconv.ParseInt(value, 10, 64) 406 if err != nil { 407 return nil, xerrors.Errorf("failed to parse uses count '%s': %w", value, err) 408 } 409 usesCount = count 410 case int(common.ICAT_COLUMN_TICKET_EXPIRY_TS): 411 if len(strings.TrimSpace(value)) > 0 { 412 mT, err := util.GetIRODSDateTime(value) 413 if err != nil { 414 return nil, xerrors.Errorf("failed to parse expiry time '%s': %w", value, err) 415 } 416 expirationTime = mT 417 } 418 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT): 419 limit, err := strconv.ParseInt(value, 10, 64) 420 if err != nil { 421 return nil, xerrors.Errorf("failed to parse write file limit '%s': %w", value, err) 422 } 423 writeFileLimit = limit 424 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT): 425 count, err := strconv.ParseInt(value, 10, 64) 426 if err != nil { 427 return nil, xerrors.Errorf("failed to parse write file count '%s': %w", value, err) 428 } 429 writeFileCount = count 430 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT): 431 limit, err := strconv.ParseInt(value, 10, 64) 432 if err != nil { 433 return nil, xerrors.Errorf("failed to parse write byte limit '%s': %w", value, err) 434 } 435 writeByteLimit = limit 436 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT): 437 count, err := strconv.ParseInt(value, 10, 64) 438 if err != nil { 439 return nil, xerrors.Errorf("failed to parse write byte count '%s': %w", value, err) 440 } 441 writeByteCount = count 442 case int(common.ICAT_COLUMN_TICKET_COLL_NAME): 443 ticketPath = value 444 case int(common.ICAT_COLUMN_TICKET_OWNER_NAME): 445 owner = value 446 case int(common.ICAT_COLUMN_TICKET_OWNER_ZONE): 447 ownerZone = value 448 default: 449 // ignore 450 } 451 } 452 453 if ticketID == -1 { 454 return nil, xerrors.Errorf("failed to find the ticket for name %s: %w", ticketName, types.NewTicketNotFoundError(ticketName)) 455 } 456 457 return &types.IRODSTicket{ 458 ID: ticketID, 459 Name: ticketName, 460 Type: ticketType, 461 Owner: owner, 462 OwnerZone: ownerZone, 463 ObjectType: objectType, 464 Path: ticketPath, 465 ExpirationTime: expirationTime, 466 UsesLimit: usesLimit, 467 UsesCount: usesCount, 468 WriteFileLimit: writeFileLimit, 469 WriteFileCount: writeFileCount, 470 WriteByteLimit: writeByteLimit, 471 WriteByteCount: writeByteCount, 472 }, nil 473 } 474 475 // ListTickets returns tickets 476 func ListTickets(conn *connection.IRODSConnection) ([]*types.IRODSTicket, error) { 477 if conn == nil || !conn.IsConnected() { 478 return nil, xerrors.Errorf("connection is nil or disconnected") 479 } 480 481 tickets := []*types.IRODSTicket{} 482 483 ticketsColl, err := ListTicketsForCollections(conn) 484 if err != nil { 485 return nil, err 486 } 487 488 tickets = append(tickets, ticketsColl...) 489 490 ticketsDataObj, err := ListTicketsForDataObjects(conn) 491 if err != nil { 492 return nil, err 493 } 494 495 tickets = append(tickets, ticketsDataObj...) 496 497 return tickets, nil 498 } 499 500 // ListTicketsForDataObjects returns tickets for data objects 501 func ListTicketsForDataObjects(conn *connection.IRODSConnection) ([]*types.IRODSTicket, error) { 502 if conn == nil || !conn.IsConnected() { 503 return nil, xerrors.Errorf("connection is nil or disconnected") 504 } 505 506 // lock the connection 507 conn.Lock() 508 defer conn.Unlock() 509 510 tickets := []*types.IRODSTicket{} 511 512 continueQuery := true 513 continueIndex := 0 514 for continueQuery { 515 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 516 query.AddSelect(common.ICAT_COLUMN_TICKET_ID, 1) 517 query.AddSelect(common.ICAT_COLUMN_TICKET_STRING, 1) 518 query.AddSelect(common.ICAT_COLUMN_TICKET_TYPE, 1) 519 query.AddSelect(common.ICAT_COLUMN_TICKET_OBJECT_TYPE, 1) 520 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_LIMIT, 1) 521 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_COUNT, 1) 522 query.AddSelect(common.ICAT_COLUMN_TICKET_EXPIRY_TS, 1) 523 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT, 1) 524 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT, 1) 525 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT, 1) 526 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT, 1) 527 query.AddSelect(common.ICAT_COLUMN_TICKET_DATA_NAME, 1) 528 query.AddSelect(common.ICAT_COLUMN_TICKET_DATA_COLL_NAME, 1) 529 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_NAME, 1) 530 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_ZONE, 1) 531 532 queryResult := message.IRODSMessageQueryResponse{} 533 err := conn.Request(query, &queryResult, nil) 534 if err != nil { 535 return nil, xerrors.Errorf("failed to receive a ticket query result message: %w", err) 536 } 537 538 err = queryResult.CheckError() 539 if err != nil { 540 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 541 // empty 542 break 543 } 544 545 return nil, xerrors.Errorf("received a ticket query error: %w", err) 546 } 547 548 if queryResult.RowCount == 0 { 549 break 550 } 551 552 if queryResult.AttributeCount > len(queryResult.SQLResult) { 553 return nil, xerrors.Errorf("failed to receive ticket attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 554 } 555 556 pagenatedTickets := make([]*types.IRODSTicket, queryResult.RowCount) 557 tempValues := make([]map[string]string, queryResult.RowCount) 558 559 for attr := 0; attr < queryResult.AttributeCount; attr++ { 560 sqlResult := queryResult.SQLResult[attr] 561 if len(sqlResult.Values) != queryResult.RowCount { 562 return nil, xerrors.Errorf("failed to receive ticket rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 563 } 564 565 for row := 0; row < queryResult.RowCount; row++ { 566 value := sqlResult.Values[row] 567 568 if pagenatedTickets[row] == nil { 569 // create a new 570 pagenatedTickets[row] = &types.IRODSTicket{ 571 ID: -1, 572 Name: "", 573 Type: types.TicketTypeRead, 574 Owner: "", 575 OwnerZone: "", 576 ObjectType: types.ObjectTypeCollection, 577 Path: "", 578 ExpirationTime: time.Time{}, 579 UsesLimit: 0, 580 UsesCount: 0, 581 WriteFileLimit: 0, 582 WriteFileCount: 0, 583 WriteByteLimit: 0, 584 WriteByteCount: 0, 585 } 586 } 587 588 if tempValues[row] == nil { 589 // create a new 590 tempValues[row] = map[string]string{} 591 } 592 593 switch sqlResult.AttributeIndex { 594 case int(common.ICAT_COLUMN_TICKET_ID): 595 tID, err := strconv.ParseInt(value, 10, 64) 596 if err != nil { 597 return nil, xerrors.Errorf("failed to parse ticket id '%s': %w", value, err) 598 } 599 pagenatedTickets[row].ID = tID 600 case int(common.ICAT_COLUMN_TICKET_STRING): 601 pagenatedTickets[row].Name = value 602 case int(common.ICAT_COLUMN_TICKET_TYPE): 603 pagenatedTickets[row].Type = types.TicketType(value) 604 case int(common.ICAT_COLUMN_TICKET_OBJECT_TYPE): 605 pagenatedTickets[row].ObjectType = types.ObjectType(value) 606 case int(common.ICAT_COLUMN_TICKET_USES_LIMIT): 607 limit, err := strconv.ParseInt(value, 10, 64) 608 if err != nil { 609 return nil, xerrors.Errorf("failed to parse uses limit '%s': %w", value, err) 610 } 611 pagenatedTickets[row].UsesLimit = limit 612 case int(common.ICAT_COLUMN_TICKET_USES_COUNT): 613 count, err := strconv.ParseInt(value, 10, 64) 614 if err != nil { 615 return nil, xerrors.Errorf("failed to parse uses count '%s': %w", value, err) 616 } 617 pagenatedTickets[row].UsesCount = count 618 case int(common.ICAT_COLUMN_TICKET_EXPIRY_TS): 619 if len(strings.TrimSpace(value)) > 0 { 620 mT, err := util.GetIRODSDateTime(value) 621 if err != nil { 622 return nil, xerrors.Errorf("failed to parse expiry time '%s': %w", value, err) 623 } 624 pagenatedTickets[row].ExpirationTime = mT 625 } 626 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT): 627 limit, err := strconv.ParseInt(value, 10, 64) 628 if err != nil { 629 return nil, xerrors.Errorf("failed to parse write file limit '%s': %w", value, err) 630 } 631 pagenatedTickets[row].WriteFileLimit = limit 632 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT): 633 count, err := strconv.ParseInt(value, 10, 64) 634 if err != nil { 635 return nil, xerrors.Errorf("failed to parse write file count '%s': %w", value, err) 636 } 637 pagenatedTickets[row].WriteFileCount = count 638 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT): 639 limit, err := strconv.ParseInt(value, 10, 64) 640 if err != nil { 641 return nil, xerrors.Errorf("failed to parse write byte limit '%s': %w", value, err) 642 } 643 pagenatedTickets[row].WriteByteLimit = limit 644 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT): 645 count, err := strconv.ParseInt(value, 10, 64) 646 if err != nil { 647 return nil, xerrors.Errorf("failed to parse write byte count '%s': %w", value, err) 648 } 649 pagenatedTickets[row].WriteByteCount = count 650 case int(common.ICAT_COLUMN_TICKET_DATA_NAME): 651 tempValues[row]["data_name"] = value 652 if dataCollName, ok := tempValues[row]["data_coll_name"]; ok { 653 pagenatedTickets[row].Path = util.MakeIRODSPath(dataCollName, value) 654 } 655 case int(common.ICAT_COLUMN_TICKET_DATA_COLL_NAME): 656 tempValues[row]["data_coll_name"] = value 657 if dataName, ok := tempValues[row]["data_name"]; ok { 658 pagenatedTickets[row].Path = util.MakeIRODSPath(value, dataName) 659 } 660 case int(common.ICAT_COLUMN_TICKET_OWNER_NAME): 661 pagenatedTickets[row].Owner = value 662 case int(common.ICAT_COLUMN_TICKET_OWNER_ZONE): 663 pagenatedTickets[row].OwnerZone = value 664 default: 665 // ignore 666 } 667 } 668 } 669 670 tickets = append(tickets, pagenatedTickets...) 671 672 continueIndex = queryResult.ContinueIndex 673 if continueIndex == 0 { 674 continueQuery = false 675 } 676 } 677 678 return tickets, nil 679 } 680 681 // ListTicketsForCollections returns tickets for collections 682 func ListTicketsForCollections(conn *connection.IRODSConnection) ([]*types.IRODSTicket, error) { 683 if conn == nil || !conn.IsConnected() { 684 return nil, xerrors.Errorf("connection is nil or disconnected") 685 } 686 687 // lock the connection 688 conn.Lock() 689 defer conn.Unlock() 690 691 tickets := []*types.IRODSTicket{} 692 693 continueQuery := true 694 continueIndex := 0 695 for continueQuery { 696 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 697 query.AddSelect(common.ICAT_COLUMN_TICKET_ID, 1) 698 query.AddSelect(common.ICAT_COLUMN_TICKET_STRING, 1) 699 query.AddSelect(common.ICAT_COLUMN_TICKET_TYPE, 1) 700 query.AddSelect(common.ICAT_COLUMN_TICKET_OBJECT_TYPE, 1) 701 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_LIMIT, 1) 702 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_COUNT, 1) 703 query.AddSelect(common.ICAT_COLUMN_TICKET_EXPIRY_TS, 1) 704 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT, 1) 705 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT, 1) 706 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT, 1) 707 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT, 1) 708 query.AddSelect(common.ICAT_COLUMN_TICKET_COLL_NAME, 1) 709 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_NAME, 1) 710 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_ZONE, 1) 711 712 queryResult := message.IRODSMessageQueryResponse{} 713 err := conn.Request(query, &queryResult, nil) 714 if err != nil { 715 return nil, xerrors.Errorf("failed to receive a ticket query result message: %w", err) 716 } 717 718 err = queryResult.CheckError() 719 if err != nil { 720 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 721 // empty 722 break 723 } 724 725 return nil, xerrors.Errorf("received a ticket query error: %w", err) 726 } 727 728 if queryResult.RowCount == 0 { 729 break 730 } 731 732 if queryResult.AttributeCount > len(queryResult.SQLResult) { 733 return nil, xerrors.Errorf("failed to receive ticket attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 734 } 735 736 pagenatedTickets := make([]*types.IRODSTicket, queryResult.RowCount) 737 738 for attr := 0; attr < queryResult.AttributeCount; attr++ { 739 sqlResult := queryResult.SQLResult[attr] 740 if len(sqlResult.Values) != queryResult.RowCount { 741 return nil, xerrors.Errorf("failed to receive ticket rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 742 } 743 744 for row := 0; row < queryResult.RowCount; row++ { 745 value := sqlResult.Values[row] 746 747 if pagenatedTickets[row] == nil { 748 // create a new 749 pagenatedTickets[row] = &types.IRODSTicket{ 750 ID: -1, 751 Name: "", 752 Type: types.TicketTypeRead, 753 Owner: "", 754 OwnerZone: "", 755 ObjectType: types.ObjectTypeCollection, 756 Path: "", 757 ExpirationTime: time.Time{}, 758 UsesLimit: 0, 759 UsesCount: 0, 760 WriteFileLimit: 0, 761 WriteFileCount: 0, 762 WriteByteLimit: 0, 763 WriteByteCount: 0, 764 } 765 } 766 767 switch sqlResult.AttributeIndex { 768 case int(common.ICAT_COLUMN_TICKET_ID): 769 tID, err := strconv.ParseInt(value, 10, 64) 770 if err != nil { 771 return nil, xerrors.Errorf("failed to parse ticket id '%s': %w", value, err) 772 } 773 pagenatedTickets[row].ID = tID 774 case int(common.ICAT_COLUMN_TICKET_STRING): 775 pagenatedTickets[row].Name = value 776 case int(common.ICAT_COLUMN_TICKET_TYPE): 777 pagenatedTickets[row].Type = types.TicketType(value) 778 case int(common.ICAT_COLUMN_TICKET_OBJECT_TYPE): 779 pagenatedTickets[row].ObjectType = types.ObjectType(value) 780 case int(common.ICAT_COLUMN_TICKET_USES_LIMIT): 781 limit, err := strconv.ParseInt(value, 10, 64) 782 if err != nil { 783 return nil, xerrors.Errorf("failed to parse uses limit '%s': %w", value, err) 784 } 785 pagenatedTickets[row].UsesLimit = limit 786 case int(common.ICAT_COLUMN_TICKET_USES_COUNT): 787 count, err := strconv.ParseInt(value, 10, 64) 788 if err != nil { 789 return nil, xerrors.Errorf("failed to parse uses count '%s': %w", value, err) 790 } 791 pagenatedTickets[row].UsesCount = count 792 case int(common.ICAT_COLUMN_TICKET_EXPIRY_TS): 793 if len(strings.TrimSpace(value)) > 0 { 794 mT, err := util.GetIRODSDateTime(value) 795 if err != nil { 796 return nil, xerrors.Errorf("failed to parse expiry time '%s': %w", value, err) 797 } 798 pagenatedTickets[row].ExpirationTime = mT 799 } 800 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT): 801 limit, err := strconv.ParseInt(value, 10, 64) 802 if err != nil { 803 return nil, xerrors.Errorf("failed to parse write file limit '%s': %w", value, err) 804 } 805 pagenatedTickets[row].WriteFileLimit = limit 806 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT): 807 count, err := strconv.ParseInt(value, 10, 64) 808 if err != nil { 809 return nil, xerrors.Errorf("failed to parse write file count '%s': %w", value, err) 810 } 811 pagenatedTickets[row].WriteFileCount = count 812 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT): 813 limit, err := strconv.ParseInt(value, 10, 64) 814 if err != nil { 815 return nil, xerrors.Errorf("failed to parse write byte limit '%s': %w", value, err) 816 } 817 pagenatedTickets[row].WriteByteLimit = limit 818 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT): 819 count, err := strconv.ParseInt(value, 10, 64) 820 if err != nil { 821 return nil, xerrors.Errorf("failed to parse write byte count '%s': %w", value, err) 822 } 823 pagenatedTickets[row].WriteByteCount = count 824 case int(common.ICAT_COLUMN_TICKET_COLL_NAME): 825 pagenatedTickets[row].Path = value 826 case int(common.ICAT_COLUMN_TICKET_OWNER_NAME): 827 pagenatedTickets[row].Owner = value 828 case int(common.ICAT_COLUMN_TICKET_OWNER_ZONE): 829 pagenatedTickets[row].OwnerZone = value 830 default: 831 // ignore 832 } 833 } 834 } 835 836 tickets = append(tickets, pagenatedTickets...) 837 838 continueIndex = queryResult.ContinueIndex 839 if continueIndex == 0 { 840 continueQuery = false 841 } 842 } 843 844 return tickets, nil 845 } 846 847 // ListTicketsBasic returns tickets with basic info 848 func ListTicketsBasic(conn *connection.IRODSConnection) ([]*types.IRODSTicket, error) { 849 if conn == nil || !conn.IsConnected() { 850 return nil, xerrors.Errorf("connection is nil or disconnected") 851 } 852 853 // lock the connection 854 conn.Lock() 855 defer conn.Unlock() 856 857 tickets := []*types.IRODSTicket{} 858 859 continueQuery := true 860 continueIndex := 0 861 for continueQuery { 862 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 863 query.AddSelect(common.ICAT_COLUMN_TICKET_ID, 1) 864 query.AddSelect(common.ICAT_COLUMN_TICKET_STRING, 1) 865 query.AddSelect(common.ICAT_COLUMN_TICKET_TYPE, 1) 866 query.AddSelect(common.ICAT_COLUMN_TICKET_OBJECT_TYPE, 1) 867 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_LIMIT, 1) 868 query.AddSelect(common.ICAT_COLUMN_TICKET_USES_COUNT, 1) 869 query.AddSelect(common.ICAT_COLUMN_TICKET_EXPIRY_TS, 1) 870 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT, 1) 871 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT, 1) 872 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT, 1) 873 query.AddSelect(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT, 1) 874 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_NAME, 1) 875 query.AddSelect(common.ICAT_COLUMN_TICKET_OWNER_ZONE, 1) 876 877 queryResult := message.IRODSMessageQueryResponse{} 878 err := conn.Request(query, &queryResult, nil) 879 if err != nil { 880 return nil, xerrors.Errorf("failed to receive a ticket query result message: %w", err) 881 } 882 883 err = queryResult.CheckError() 884 if err != nil { 885 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 886 // empty 887 break 888 } 889 890 return nil, xerrors.Errorf("received a ticket query error: %w", err) 891 } 892 893 if queryResult.RowCount == 0 { 894 break 895 } 896 897 if queryResult.AttributeCount > len(queryResult.SQLResult) { 898 return nil, xerrors.Errorf("failed to receive ticket attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 899 } 900 901 pagenatedTickets := make([]*types.IRODSTicket, queryResult.RowCount) 902 903 for attr := 0; attr < queryResult.AttributeCount; attr++ { 904 sqlResult := queryResult.SQLResult[attr] 905 if len(sqlResult.Values) != queryResult.RowCount { 906 return nil, xerrors.Errorf("failed to receive ticket rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 907 } 908 909 for row := 0; row < queryResult.RowCount; row++ { 910 value := sqlResult.Values[row] 911 912 if pagenatedTickets[row] == nil { 913 // create a new 914 pagenatedTickets[row] = &types.IRODSTicket{ 915 ID: -1, 916 Name: "", 917 Type: types.TicketTypeRead, 918 Owner: "", 919 OwnerZone: "", 920 ObjectType: types.ObjectTypeCollection, 921 Path: "", 922 ExpirationTime: time.Time{}, 923 UsesLimit: 0, 924 UsesCount: 0, 925 WriteFileLimit: 0, 926 WriteFileCount: 0, 927 WriteByteLimit: 0, 928 WriteByteCount: 0, 929 } 930 } 931 932 switch sqlResult.AttributeIndex { 933 case int(common.ICAT_COLUMN_TICKET_ID): 934 tID, err := strconv.ParseInt(value, 10, 64) 935 if err != nil { 936 return nil, xerrors.Errorf("failed to parse ticket id '%s': %w", value, err) 937 } 938 pagenatedTickets[row].ID = tID 939 case int(common.ICAT_COLUMN_TICKET_STRING): 940 pagenatedTickets[row].Name = value 941 case int(common.ICAT_COLUMN_TICKET_TYPE): 942 pagenatedTickets[row].Type = types.TicketType(value) 943 case int(common.ICAT_COLUMN_TICKET_OBJECT_TYPE): 944 pagenatedTickets[row].ObjectType = types.ObjectType(value) 945 case int(common.ICAT_COLUMN_TICKET_USES_LIMIT): 946 limit, err := strconv.ParseInt(value, 10, 64) 947 if err != nil { 948 return nil, xerrors.Errorf("failed to parse uses limit '%s': %w", value, err) 949 } 950 pagenatedTickets[row].UsesLimit = limit 951 case int(common.ICAT_COLUMN_TICKET_USES_COUNT): 952 count, err := strconv.ParseInt(value, 10, 64) 953 if err != nil { 954 return nil, xerrors.Errorf("failed to parse uses count '%s': %w", value, err) 955 } 956 pagenatedTickets[row].UsesCount = count 957 case int(common.ICAT_COLUMN_TICKET_EXPIRY_TS): 958 if len(strings.TrimSpace(value)) > 0 { 959 mT, err := util.GetIRODSDateTime(value) 960 if err != nil { 961 return nil, xerrors.Errorf("failed to parse expiry time '%s': %w", value, err) 962 } 963 pagenatedTickets[row].ExpirationTime = mT 964 } 965 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_LIMIT): 966 limit, err := strconv.ParseInt(value, 10, 64) 967 if err != nil { 968 return nil, xerrors.Errorf("failed to parse write file limit '%s': %w", value, err) 969 } 970 pagenatedTickets[row].WriteFileLimit = limit 971 case int(common.ICAT_COLUMN_TICKET_WRITE_FILE_COUNT): 972 count, err := strconv.ParseInt(value, 10, 64) 973 if err != nil { 974 return nil, xerrors.Errorf("failed to parse write file count '%s': %w", value, err) 975 } 976 pagenatedTickets[row].WriteFileCount = count 977 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_LIMIT): 978 limit, err := strconv.ParseInt(value, 10, 64) 979 if err != nil { 980 return nil, xerrors.Errorf("failed to parse write byte limit '%s': %w", value, err) 981 } 982 pagenatedTickets[row].WriteByteLimit = limit 983 case int(common.ICAT_COLUMN_TICKET_WRITE_BYTE_COUNT): 984 count, err := strconv.ParseInt(value, 10, 64) 985 if err != nil { 986 return nil, xerrors.Errorf("failed to parse write byte count '%s': %w", value, err) 987 } 988 pagenatedTickets[row].WriteByteCount = count 989 case int(common.ICAT_COLUMN_TICKET_OWNER_NAME): 990 pagenatedTickets[row].Owner = value 991 case int(common.ICAT_COLUMN_TICKET_OWNER_ZONE): 992 pagenatedTickets[row].OwnerZone = value 993 default: 994 // ignore 995 } 996 } 997 } 998 999 tickets = append(tickets, pagenatedTickets...) 1000 1001 continueIndex = queryResult.ContinueIndex 1002 if continueIndex == 0 { 1003 continueQuery = false 1004 } 1005 } 1006 1007 return tickets, nil 1008 } 1009 1010 // ListTicketAllowedHosts returns allowed hosts for the given ticket 1011 func ListTicketAllowedHosts(conn *connection.IRODSConnection, ticketID int64) ([]string, error) { 1012 if conn == nil || !conn.IsConnected() { 1013 return nil, xerrors.Errorf("connection is nil or disconnected") 1014 } 1015 1016 // lock the connection 1017 conn.Lock() 1018 defer conn.Unlock() 1019 1020 hosts := []string{} 1021 1022 continueQuery := true 1023 continueIndex := 0 1024 for continueQuery { 1025 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 1026 query.AddSelect(common.ICAT_COLUMN_TICKET_ALLOWED_HOST, 1) 1027 1028 collCondVal := fmt.Sprintf("= '%d'", ticketID) 1029 query.AddCondition(common.ICAT_COLUMN_TICKET_ALLOWED_HOST_TICKET_ID, collCondVal) 1030 1031 queryResult := message.IRODSMessageQueryResponse{} 1032 err := conn.Request(query, &queryResult, nil) 1033 if err != nil { 1034 return nil, xerrors.Errorf("failed to receive a ticket restriction query result message: %w", err) 1035 } 1036 1037 err = queryResult.CheckError() 1038 if err != nil { 1039 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 1040 // empty 1041 break 1042 } 1043 1044 return nil, xerrors.Errorf("received a ticket restriction query error: %w", err) 1045 } 1046 1047 if queryResult.RowCount == 0 { 1048 break 1049 } 1050 1051 if queryResult.AttributeCount > len(queryResult.SQLResult) { 1052 return nil, xerrors.Errorf("failed to receive ticket restriction attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 1053 } 1054 1055 pagenatedHosts := make([]string, queryResult.RowCount) 1056 1057 for attr := 0; attr < queryResult.AttributeCount; attr++ { 1058 sqlResult := queryResult.SQLResult[attr] 1059 if len(sqlResult.Values) != queryResult.RowCount { 1060 return nil, xerrors.Errorf("failed to receive ticket restriction rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 1061 } 1062 1063 for row := 0; row < queryResult.RowCount; row++ { 1064 value := sqlResult.Values[row] 1065 1066 switch sqlResult.AttributeIndex { 1067 case int(common.ICAT_COLUMN_TICKET_ALLOWED_HOST): 1068 pagenatedHosts[row] = value 1069 default: 1070 // ignore 1071 } 1072 } 1073 } 1074 1075 hosts = append(hosts, pagenatedHosts...) 1076 1077 continueIndex = queryResult.ContinueIndex 1078 if continueIndex == 0 { 1079 continueQuery = false 1080 } 1081 } 1082 1083 return hosts, nil 1084 } 1085 1086 // ListTicketAllowedUserNames returns allowed user names for the given ticket 1087 func ListTicketAllowedUserNames(conn *connection.IRODSConnection, ticketID int64) ([]string, error) { 1088 if conn == nil || !conn.IsConnected() { 1089 return nil, xerrors.Errorf("connection is nil or disconnected") 1090 } 1091 1092 // lock the connection 1093 conn.Lock() 1094 defer conn.Unlock() 1095 1096 usernames := []string{} 1097 1098 continueQuery := true 1099 continueIndex := 0 1100 for continueQuery { 1101 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 1102 query.AddSelect(common.ICAT_COLUMN_TICKET_ALLOWED_USER_NAME, 1) 1103 1104 collCondVal := fmt.Sprintf("= '%d'", ticketID) 1105 query.AddCondition(common.ICAT_COLUMN_TICKET_ALLOWED_USER_TICKET_ID, collCondVal) 1106 1107 queryResult := message.IRODSMessageQueryResponse{} 1108 err := conn.Request(query, &queryResult, nil) 1109 if err != nil { 1110 return nil, xerrors.Errorf("failed to receive a ticket restriction query result message: %w", err) 1111 } 1112 1113 err = queryResult.CheckError() 1114 if err != nil { 1115 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 1116 // empty 1117 break 1118 } 1119 1120 return nil, xerrors.Errorf("received a ticket restriction query error: %w", err) 1121 } 1122 1123 if queryResult.RowCount == 0 { 1124 break 1125 } 1126 1127 if queryResult.AttributeCount > len(queryResult.SQLResult) { 1128 return nil, xerrors.Errorf("failed to receive ticket restriction attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 1129 } 1130 1131 pagenatedUsernames := make([]string, queryResult.RowCount) 1132 1133 for attr := 0; attr < queryResult.AttributeCount; attr++ { 1134 sqlResult := queryResult.SQLResult[attr] 1135 if len(sqlResult.Values) != queryResult.RowCount { 1136 return nil, xerrors.Errorf("failed to receive ticket restriction rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 1137 } 1138 1139 for row := 0; row < queryResult.RowCount; row++ { 1140 value := sqlResult.Values[row] 1141 1142 switch sqlResult.AttributeIndex { 1143 case int(common.ICAT_COLUMN_TICKET_ALLOWED_USER_NAME): 1144 pagenatedUsernames[row] = value 1145 default: 1146 // ignore 1147 } 1148 } 1149 } 1150 1151 usernames = append(usernames, pagenatedUsernames...) 1152 1153 continueIndex = queryResult.ContinueIndex 1154 if continueIndex == 0 { 1155 continueQuery = false 1156 } 1157 } 1158 1159 return usernames, nil 1160 } 1161 1162 // ListTicketAllowedGroupNames returns allowed group names for the given ticket 1163 func ListTicketAllowedGroupNames(conn *connection.IRODSConnection, ticketID int64) ([]string, error) { 1164 if conn == nil || !conn.IsConnected() { 1165 return nil, xerrors.Errorf("connection is nil or disconnected") 1166 } 1167 1168 // lock the connection 1169 conn.Lock() 1170 defer conn.Unlock() 1171 1172 groupnames := []string{} 1173 1174 continueQuery := true 1175 continueIndex := 0 1176 for continueQuery { 1177 query := message.NewIRODSMessageQueryRequest(common.MaxQueryRows, continueIndex, 0, 0) 1178 query.AddSelect(common.ICAT_COLUMN_TICKET_ALLOWED_GROUP_NAME, 1) 1179 1180 collCondVal := fmt.Sprintf("= '%d'", ticketID) 1181 query.AddCondition(common.ICAT_COLUMN_TICKET_ALLOWED_GROUP_TICKET_ID, collCondVal) 1182 1183 queryResult := message.IRODSMessageQueryResponse{} 1184 err := conn.Request(query, &queryResult, nil) 1185 if err != nil { 1186 return nil, xerrors.Errorf("failed to receive a ticket restriction query result message: %w", err) 1187 } 1188 1189 err = queryResult.CheckError() 1190 if err != nil { 1191 if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { 1192 // empty 1193 break 1194 } 1195 1196 return nil, xerrors.Errorf("received a ticket restriction query error: %w", err) 1197 } 1198 1199 if queryResult.RowCount == 0 { 1200 break 1201 } 1202 1203 if queryResult.AttributeCount > len(queryResult.SQLResult) { 1204 return nil, xerrors.Errorf("failed to receive ticket restriction attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) 1205 } 1206 1207 pagenatedGroupnames := make([]string, queryResult.RowCount) 1208 1209 for attr := 0; attr < queryResult.AttributeCount; attr++ { 1210 sqlResult := queryResult.SQLResult[attr] 1211 if len(sqlResult.Values) != queryResult.RowCount { 1212 return nil, xerrors.Errorf("failed to receive ticket restriction rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) 1213 } 1214 1215 for row := 0; row < queryResult.RowCount; row++ { 1216 value := sqlResult.Values[row] 1217 1218 switch sqlResult.AttributeIndex { 1219 case int(common.ICAT_COLUMN_TICKET_ALLOWED_GROUP_NAME): 1220 pagenatedGroupnames[row] = value 1221 default: 1222 // ignore 1223 } 1224 } 1225 } 1226 1227 groupnames = append(groupnames, pagenatedGroupnames...) 1228 1229 continueIndex = queryResult.ContinueIndex 1230 if continueIndex == 0 { 1231 continueQuery = false 1232 } 1233 } 1234 1235 return groupnames, nil 1236 } 1237 1238 // CreateTicket creates a ticket 1239 func CreateTicket(conn *connection.IRODSConnection, ticketName string, ticketType types.TicketType, path string) error { 1240 // lock the connection 1241 conn.Lock() 1242 defer conn.Unlock() 1243 1244 ticketName = strings.TrimSpace(ticketName) 1245 if len(ticketName) == 0 { 1246 ticketName = xid.New().String() 1247 } 1248 1249 req := message.NewIRODSMessageTicketAdminRequest("create", ticketName, string(ticketType), path, ticketName) 1250 1251 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 1252 if err != nil { 1253 return xerrors.Errorf("received create ticket error: %w", err) 1254 } 1255 return nil 1256 } 1257 1258 // DeleteTicket deletes the ticket 1259 func DeleteTicket(conn *connection.IRODSConnection, ticketName string) error { 1260 // lock the connection 1261 conn.Lock() 1262 defer conn.Unlock() 1263 1264 req := message.NewIRODSMessageTicketAdminRequest("delete", ticketName) 1265 1266 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 1267 if err != nil { 1268 return xerrors.Errorf("received delete ticket error: %w", err) 1269 } 1270 return nil 1271 } 1272 1273 // ModifyTicket modifies the given ticket 1274 func ModifyTicket(conn *connection.IRODSConnection, ticketName string, args ...string) error { 1275 // lock the connection 1276 conn.Lock() 1277 defer conn.Unlock() 1278 1279 req := message.NewIRODSMessageTicketAdminRequest("mod", ticketName, args...) 1280 1281 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 1282 if err != nil { 1283 return xerrors.Errorf("received mod ticket error: %w", err) 1284 } 1285 return nil 1286 } 1287 1288 // ModifyTicketUseLimit modifies the use limit of the given ticket 1289 func ModifyTicketUseLimit(conn *connection.IRODSConnection, ticketName string, uses int64) error { 1290 return ModifyTicket(conn, ticketName, "uses", fmt.Sprintf("%d", uses)) 1291 } 1292 1293 // ClearTicketUseLimit clears the use limit of the given ticket 1294 func ClearTicketUseLimit(conn *connection.IRODSConnection, ticketName string) error { 1295 return ModifyTicketUseLimit(conn, ticketName, 0) 1296 } 1297 1298 // ModifyTicketWriteFileLimit modifies the write file limit of the given ticket 1299 func ModifyTicketWriteFileLimit(conn *connection.IRODSConnection, ticketName string, count int64) error { 1300 return ModifyTicket(conn, ticketName, "write-file", fmt.Sprintf("%d", count)) 1301 } 1302 1303 // ClearTicketWriteFileLimit clears the write file limit of the given ticket 1304 func ClearTicketWriteFileLimit(conn *connection.IRODSConnection, ticketName string) error { 1305 return ModifyTicketWriteFileLimit(conn, ticketName, 0) 1306 } 1307 1308 // ModifyTicketWriteByteLimit modifies the write byte limit of the given ticket 1309 func ModifyTicketWriteByteLimit(conn *connection.IRODSConnection, ticketName string, bytes int64) error { 1310 return ModifyTicket(conn, ticketName, "write-bytes", fmt.Sprintf("%d", bytes)) 1311 } 1312 1313 // ClearTicketWriteByteLimit clears the write byte limit of the given ticket 1314 func ClearTicketWriteByteLimit(conn *connection.IRODSConnection, ticketName string) error { 1315 return ModifyTicketWriteByteLimit(conn, ticketName, 0) 1316 } 1317 1318 // AddTicketAllowedUser adds a user to the allowed user names list of the given ticket 1319 func AddTicketAllowedUser(conn *connection.IRODSConnection, ticketName string, userName string) error { 1320 return ModifyTicket(conn, ticketName, "add", "user", userName) 1321 } 1322 1323 // RemoveTicketAllowedUser removes the user from the allowed user names list of the given ticket 1324 func RemoveTicketAllowedUser(conn *connection.IRODSConnection, ticketName string, userName string) error { 1325 return ModifyTicket(conn, ticketName, "remove", "user", userName) 1326 } 1327 1328 // AddTicketAllowedGroup adds a group to the allowed group names list of the given ticket 1329 func AddTicketAllowedGroup(conn *connection.IRODSConnection, ticketName string, groupName string) error { 1330 return ModifyTicket(conn, ticketName, "add", "group", groupName) 1331 } 1332 1333 // RemoveTicketAllowedGroup removes the group from the allowed group names list of the given ticket 1334 func RemoveTicketAllowedGroup(conn *connection.IRODSConnection, ticketName string, groupName string) error { 1335 return ModifyTicket(conn, ticketName, "remove", "group", groupName) 1336 } 1337 1338 // AddTicketAllowedHost adds a host to the allowed hosts list of the given ticket 1339 func AddTicketAllowedHost(conn *connection.IRODSConnection, ticketName string, host string) error { 1340 return ModifyTicket(conn, ticketName, "add", "host", host) 1341 } 1342 1343 // RemoveTicketAllowedHost removes the host from the allowed hosts list of the given ticket 1344 func RemoveTicketAllowedHost(conn *connection.IRODSConnection, ticketName string, host string) error { 1345 return ModifyTicket(conn, ticketName, "remove", "host", host) 1346 } 1347 1348 // ModifyTicketExpirationTime modifies the expiration time of the given ticket 1349 func ModifyTicketExpirationTime(conn *connection.IRODSConnection, ticketName string, expirationTime time.Time) error { 1350 expirationTimeString := util.GetIRODSDateTimeStringForTicket(expirationTime) 1351 1352 return ModifyTicket(conn, ticketName, "expire", expirationTimeString) 1353 } 1354 1355 // ClearTicketExpirationTime clears the expiration time of the given ticket 1356 func ClearTicketExpirationTime(conn *connection.IRODSConnection, ticketName string) error { 1357 return ModifyTicketExpirationTime(conn, ticketName, time.Time{}) 1358 } 1359 1360 // SupplyTicket supplies a ticket to obtain access 1361 func SupplyTicket(conn *connection.IRODSConnection, ticketName string) error { 1362 // lock the connection 1363 conn.Lock() 1364 defer conn.Unlock() 1365 1366 req := message.NewIRODSMessageTicketAdminRequest("session", ticketName) 1367 err := conn.RequestAndCheck(req, &message.IRODSMessageAdminResponse{}, nil) 1368 if err != nil { 1369 return xerrors.Errorf("received supply ticket error: %w", err) 1370 } 1371 return nil 1372 }