1 = Resources = 2 3 In imip-agent, resources are a special kind of user that act upon requests 4 to schedule events and that perform such scheduling autonomously, meaning 5 that no human intervention is necessary when such resources receive messages 6 containing invitations. 7 8 By default, the [[../AgentPrograms|agent program]] responsible for resources 9 merely attempts to fit a received event into the resource's schedule. However, 10 in some organisations and environments, it is likely to be the case that other 11 policies are needed to ensure that a resource is not misused, overused or made 12 unnecessarily unavailable. 13 14 The [[../Preferences|preferences]] provide a way of controlling the behaviour 15 of resources, just as with any other kind of user, but certain preferences 16 are central to the configuration of resources. 17 18 <<TableOfContents(2,4)>> 19 20 == Scheduling Functions == 21 22 The [[../Preferences#scheduling_function|scheduling_function]] setting 23 indicates the behaviour of a resource when a valid request to schedule an 24 event has been received. By default, a value equivalent to the following is 25 employed: 26 27 {{{{#!table 28 '''Scheduling Functions''' || '''Decision Process''' 29 == 30 <style="vertical-align: top;"> 31 32 {{{ 33 schedule_in_freebusy 34 }}} 35 36 || 37 38 {{{#!graphviz 39 //format=svg 40 //transform=notugly 41 digraph scheduling_decisions { 42 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 43 edge [tooltip="Scheduling decisions"]; 44 45 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 46 47 subgraph { 48 rank=same; 49 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 50 freebusy [label="Free/busy",shape=folder]; 51 } 52 53 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 54 55 subgraph { 56 rank=same; 57 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 58 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 59 } 60 61 mail -> schedule_in_freebusy -> schedule -> accept; 62 schedule_in_freebusy -> decline [style=dashed]; 63 freebusy -> schedule_in_freebusy; 64 } 65 }}} 66 67 }}}} 68 69 As described above, this merely attempts to schedule an event in the free 70 periods of the resource's schedule. However, no attempt is made to reject the 71 booking of the resource according to the identity of the organiser. 72 73 === Identity Controls === 74 75 Although identity controls may be implemented in the e-mail system, 76 effectively preventing the messages from addresses other than those within 77 an organisation (for example) from being delivered to the resource, it is 78 possible to use scheduling functions to implement such controls instead. 79 80 ==== Same Domain Membership ==== 81 82 For instance, the following combines the default free/busy check with a 83 test that the organiser belongs to the same Internet mail domain (by using 84 the organiser's address): 85 86 {{{{#!table 87 '''Scheduling Functions''' || '''Decision Process''' 88 == 89 <style="vertical-align: top;"> 90 91 {{{ 92 schedule_in_freebusy 93 same_domain_only 94 }}} 95 96 || 97 98 {{{#!graphviz 99 //format=svg 100 //transform=notugly 101 digraph scheduling_decisions { 102 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 103 edge [tooltip="Scheduling decisions"]; 104 105 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 106 107 subgraph { 108 rank=same; 109 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 110 freebusy [label="Free/busy",shape=folder]; 111 } 112 113 same_domain_only [label="Organiser has resource domain?",shape=ellipse,style=filled,fillcolor=gold]; 114 115 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 116 117 subgraph { 118 rank=same; 119 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 120 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 121 } 122 123 mail -> schedule_in_freebusy -> same_domain_only -> schedule -> accept; 124 schedule_in_freebusy -> decline [style=dashed]; 125 same_domain_only -> decline [style=dashed]; 126 freebusy -> schedule_in_freebusy; 127 } 128 }}} 129 130 }}}} 131 132 Note that if the first function is omitted, no check against the resource's 133 schedule will occur, so it is necessary to mention any such function in the 134 list. 135 136 ==== Access Control Lists ==== 137 138 A simple domain-related test may not be sufficient to control access to a 139 resource. Thus, another function is provided to exercise a finer degree of 140 control over event participants. For example: 141 142 {{{{#!table 143 '''Scheduling Functions and Data''' || '''Decision Process''' 144 == 145 <style="vertical-align: top;"> 146 147 {{{ 148 schedule_in_freebusy 149 access_control_list 150 }}} 151 152 Access control list: 153 154 {{{ 155 accept 156 }}} 157 158 || 159 160 {{{#!graphviz 161 //format=svg 162 //transform=notugly 163 digraph scheduling_decisions { 164 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 165 edge [tooltip="Scheduling decisions"]; 166 167 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 168 169 subgraph { 170 rank=same; 171 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 172 freebusy [label="Free/busy",shape=folder]; 173 } 174 175 subgraph { 176 rank=same; 177 access_control_list [label="Access control list permits booking?",shape=ellipse,style=filled,fillcolor=gold]; 178 acl [label="acl setting",shape=folder]; 179 } 180 181 accept_default [label="Accept invitation by default",shape=ellipse,style=filled,fillcolor=darkorange]; 182 end_acl [label="end",shape=ellipse,style=filled,fillcolor=darkorange]; 183 184 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 185 186 subgraph { 187 rank=same; 188 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 189 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 190 } 191 192 mail -> schedule_in_freebusy -> access_control_list -> accept_default -> end_acl -> schedule -> accept; 193 end_acl -> decline [style=dashed]; 194 schedule_in_freebusy -> decline [style=dashed]; 195 freebusy -> schedule_in_freebusy; 196 acl -> access_control_list; 197 } 198 }}} 199 200 }}}} 201 202 To accompany the scheduling functions, the [[../Preferences#acl|acl]] setting 203 in the resource's preferences must be set, or if a separate file is more 204 appropriate, its full path may be given as an argument to `access_control_list`: 205 206 {{{ 207 schedule_in_freebusy 208 access_control_list /etc/imip-agent/resources.acl 209 }}} 210 211 Within the file provided by the setting or separate file, a list of rules 212 must describe the handling procedure for an event. For example, the following 213 was given in the above example: 214 215 {{{ 216 accept 217 }}} 218 219 This will merely accept all invitations, anyway. However, it may be 220 appropriate to prevent certain users from using resources. For example: 221 222 {{{{#!table 223 '''Scheduling Functions and Data''' || '''Decision Process''' 224 == 225 <style="vertical-align: top;"> 226 227 {{{ 228 schedule_in_freebusy 229 access_control_list 230 }}} 231 232 Access control list: 233 234 {{{ 235 accept 236 decline attendee simon.skunk@example.com 237 }}} 238 239 || 240 241 {{{#!graphviz 242 //format=svg 243 //transform=notugly 244 digraph scheduling_decisions { 245 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 246 edge [tooltip="Scheduling decisions"]; 247 248 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 249 250 subgraph { 251 rank=same; 252 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 253 freebusy [label="Free/busy",shape=folder]; 254 } 255 256 subgraph { 257 rank=same; 258 access_control_list [label="Access control list permits booking?",shape=ellipse,style=filled,fillcolor=gold]; 259 acl [label="acl setting",shape=folder]; 260 } 261 262 accept_default [label="Accept invitation by default",shape=ellipse,style=filled,fillcolor=darkorange]; 263 decline_attendee [label="Is attendee simon.skunk@example.com?",shape=ellipse,style=filled,fillcolor=darkorange]; 264 end_acl [label="end",shape=ellipse,style=filled,fillcolor=darkorange]; 265 266 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 267 268 subgraph { 269 rank=same; 270 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 271 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 272 } 273 274 mail -> schedule_in_freebusy -> access_control_list -> accept_default -> decline_attendee -> end_acl -> schedule -> accept; 275 end_acl -> decline [style=dashed]; 276 schedule_in_freebusy -> decline [style=dashed]; 277 freebusy -> schedule_in_freebusy; 278 acl -> access_control_list; 279 } 280 }}} 281 282 }}}} 283 284 This example indicates that by default, invitations will be accepted, but if 285 one of the attendees of an event is `simon.skunk@example.com`, the invitation 286 will be declined. However, it may be the case that this rule should be 287 overridden under certain circumstances. For example: 288 289 {{{{#!table 290 '''Scheduling Functions and Data''' || '''Decision Process''' 291 == 292 <style="vertical-align: top;"> 293 294 {{{ 295 schedule_in_freebusy 296 access_control_list 297 }}} 298 299 Access control list: 300 301 {{{ 302 accept 303 decline attendee simon.skunk@example.com 304 accept organiser paul.boddie@example.com 305 }}} 306 307 || 308 309 {{{#!graphviz 310 //format=svg 311 //transform=notugly 312 digraph scheduling_decisions { 313 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 314 edge [tooltip="Scheduling decisions"]; 315 316 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 317 318 subgraph { 319 rank=same; 320 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 321 freebusy [label="Free/busy",shape=folder]; 322 } 323 324 subgraph { 325 rank=same; 326 access_control_list [label="Access control list permits booking?",shape=ellipse,style=filled,fillcolor=gold]; 327 acl [label="acl setting",shape=folder]; 328 } 329 330 accept_default [label="Accept invitation by default",shape=ellipse,style=filled,fillcolor=darkorange]; 331 decline_attendee [label="Is attendee simon.skunk@example.com?",shape=ellipse,style=filled,fillcolor=darkorange]; 332 accept_organiser [label="Is organiser paul.boddie@example.com?",shape=ellipse,style=filled,fillcolor=darkorange]; 333 end_acl [label="end",shape=ellipse,style=filled,fillcolor=darkorange]; 334 335 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 336 337 subgraph { 338 rank=same; 339 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 340 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 341 } 342 343 mail -> schedule_in_freebusy -> access_control_list -> accept_default -> decline_attendee -> accept_organiser -> end_acl -> schedule -> accept; 344 end_acl -> decline [style=dashed]; 345 schedule_in_freebusy -> decline [style=dashed]; 346 freebusy -> schedule_in_freebusy; 347 acl -> access_control_list; 348 } 349 }}} 350 351 }}}} 352 353 Here, the stated organiser may still arrange a booking of the resource where 354 the previously-mentioned attendee is involved. 355 356 === Quota Controls === 357 358 In contrast to each user's stored information which consolidates information 359 related to that user's own schedule, the quota system consolidates information 360 related to the schedules of one or more resources, thus enabling observations 361 to be made about their collective usage. 362 363 First, consider a resource such as a car where an organiser of an event may be 364 booking the car for travel purposes. A quota prevents the organiser from 365 booking the resource too much and denying other users access to it. 366 367 Now consider a number of separate car resources. An organiser might attempt to 368 get around any individual resource quota by booking a number of different cars. 369 By grouping the resources together, the organiser will exhaust a quota set on 370 the group of resources as reservations are made for the different members of 371 the group. 372 373 ==== Initialising Quotas ==== 374 375 Within the journal storage area (described in the 376 [[../FilesystemUsage|filesystem guide]] and [[../DatabaseStore|database guide]]), 377 a quota group directory must be initialised with a `limits` file indicating 378 the amount of time that can be occupied by the cumulative total of all events 379 scheduled by an individual user or a group of which they are a member. For 380 example: 381 382 {{{ 383 mailto:vincent.vole@example.com PT10H 384 }}} 385 386 This indicates that the given user may only reserve 10 hours of events or less. 387 Attempts to schedule more time will be declined. 388 389 To impose a general quota, the special `*` identity can be used: 390 391 {{{ 392 * PT10H 393 }}} 394 395 When a user identity is not listed and no general quota is defined, that 396 particular user will be unable to reserve the resource unless defined as a 397 member of a group listed in the `limits` file, as described below. 398 399 {{{{#!wiki tip 400 In a deployment using the [[../FileStore|file store]], files as described 401 above and below hold mappings and definitions in the given format. In a 402 deployment using the [[../DatabaseStore|database store]], database tables 403 hold such mappings with each column dedicated to a particular kind of 404 information. 405 406 The examples here can be transcribed by just taking each 407 element and putting it in the appropriate column within a table, making 408 sure to set the `quota` column to indicate which quota is involved. For 409 example, to set the above limits in PostgreSQL, the following operations 410 may be used: 411 412 {{{ 413 insert into quota_limits (quota, user_group, quota_limit) values ( 414 'mailto:resource-car-cadillac@example.com', 415 'mailto:vincent.vole@example.com', 416 'PT10H'); 417 insert into quota_limits (quota, user_group, quota_limit) values ( 418 'mailto:resource-car-cadillac@example.com', 419 '*', 420 'PT10H'); 421 }}} 422 423 Here, the `quota` column is set to `mailto:resource-car-cadillac@example.com`. 424 In a file-based journal, the equivalent `limits` file would be placed within a 425 quota directory having the name `mailto:resource-car-cadillac@example.com`. 426 }}}} 427 428 ==== Sharing Quotas Across Users ==== 429 430 When the use of resources is to be shared between users in such a way that 431 groups of users will be sharing a single quota, the `groups` file in the 432 quota directory must be defined, mapping each user identity to the group to 433 which they will belong. For example: 434 435 {{{ 436 mailto:vincent.vole@example.com developers 437 mailto:harvey.horse@example.com developers 438 mailto:paul.boddie@example.com developers 439 mailto:simon.skunk@example.com testers 440 }}} 441 442 The group identity can then be employed in the `limits` file: 443 444 {{{ 445 developers PT10H 446 testers PT20H 447 }}} 448 449 Limits apply to individuals, then to groups, then the general quota applies. 450 Thus, when a group is not listed, the general quota applies; without a general 451 quota (and without matching individually), a group member will be unable to 452 reserve the resource. 453 454 ==== Individual Resource Quotas ==== 455 456 The trivial case of applying quotas is to give a resource its own quota. This 457 is achieved by not specifying any arguments to the `check_quota` scheduling 458 function or to the `add_to_quota` and `remove_from_quota` functions. 459 460 {{{{#!table 461 '''Scheduling Functions''' || '''Decision Process''' 462 == 463 <style="vertical-align: top;"> 464 465 {{{ 466 check_quota 467 }}} 468 469 || 470 471 {{{#!graphviz 472 //format=svg 473 //transform=notugly 474 digraph scheduling_decisions { 475 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 476 edge [tooltip="Scheduling decisions"]; 477 478 subgraph { 479 rank=same; 480 mail [label="Incoming mail\nfrom vincent.vole@example.com",shape=folder,style=filled,fillcolor=cyan]; 481 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 482 } 483 484 subgraph { 485 rank=same; 486 check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold]; 487 quota [label="Quota for resource",shape=folder]; 488 quota_for_vole [label="...applying to\nvincent.vole@example.com",shape=folder]; 489 } 490 491 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 492 493 subgraph { 494 rank=same; 495 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 496 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 497 } 498 499 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 500 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 501 502 mail -> check_quota -> schedule -> accept; 503 check_quota -> decline [style=dashed]; 504 schedule -> add_to_quota -> quota; 505 quota -> quota_for_vole -> check_quota; 506 507 cancel -> remove_from_quota -> quota; 508 } 509 }}} 510 511 }}}} 512 513 ==== Common Resource Quotas ==== 514 515 By indicating an argument to the different functions, a common quota can be 516 employed. In the following example, both resources would employ the given 517 function invocations to pool their knowledge about their schedules. 518 519 {{{{#!table 520 '''Scheduling Functions''' || '''Decision Process''' 521 == 522 <style="vertical-align: top;"> 523 524 {{{ 525 check_quota cars 526 }}} 527 528 || 529 530 {{{#!graphviz 531 //format=svg 532 //transform=notugly 533 digraph scheduling_decisions { 534 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 535 edge [tooltip="Scheduling decisions"]; 536 537 subgraph { 538 rank=same; 539 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 540 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 541 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 542 } 543 544 subgraph { 545 rank=same; 546 check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold]; 547 quota_cars [label="Quota for cars",shape=folder]; 548 quota_cars_vole [label="...applying to\nvincent.vole@example.com",shape=folder]; 549 } 550 551 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 552 553 subgraph { 554 rank=same; 555 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 556 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 557 } 558 559 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 560 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 561 562 mail_cadillac -> check_quota; 563 mail_pontiac -> check_quota -> schedule -> accept; 564 check_quota -> decline [style=dashed]; 565 schedule -> add_to_quota -> quota_cars; 566 quota_cars -> quota_cars_vole -> check_quota; 567 568 cancel -> remove_from_quota -> quota_cars; 569 } 570 }}} 571 572 }}}} 573 574 ==== Collective Scheduling ==== 575 576 Consider two separate resources: both may be reserved at the same time by the 577 same organiser; neither resource would normally decline the reservation on the 578 basis of schedule availability, should the period concerned be free. However, 579 it may be undesirable for one organiser to occupy both resources at the same 580 time. 581 582 Consequently, a mechanism is required to pool the resource schedules in such a 583 way that any reservation performed for one resource at a given point in time 584 prohibits another reservation performed for a related resource at the same 585 point in time by the same user. 586 587 The free/busy records held for a given quota group permit such collective 588 scheduling decisions and are employed as follows: 589 590 {{{{#!table 591 '''Scheduling Functions''' || '''Decision Process''' 592 == 593 <style="vertical-align: top;"> 594 595 {{{ 596 schedule_within_quota cars 597 }}} 598 599 || 600 601 {{{#!graphviz 602 //format=svg 603 //transform=notugly 604 digraph scheduling_decisions { 605 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 606 edge [tooltip="Scheduling decisions"]; 607 608 subgraph { 609 rank=same; 610 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 611 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 612 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 613 } 614 615 subgraph { 616 rank=same; 617 schedule_across_quota [label="Can be scheduled within the quota?",shape=ellipse,style=filled,fillcolor=gold]; 618 quota_cars [label="Quota for cars",shape=folder]; 619 freebusy_cars_vole [label="...recording schedule for\nvincent.vole@example.com",shape=folder]; 620 } 621 622 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 623 624 subgraph { 625 rank=same; 626 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 627 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 628 } 629 630 add_to_quota_freebusy [label="Add to quota free/busy",shape=ellipse,style=filled,fillcolor=darkorange]; 631 remove_from_quota_freebusy [label="Remove from quota free/busy",shape=ellipse,style=filled,fillcolor=darkorange]; 632 633 mail_cadillac -> schedule_across_quota; 634 mail_pontiac -> schedule_across_quota -> schedule -> accept; 635 schedule_across_quota -> decline [style=dashed]; 636 schedule -> add_to_quota_freebusy -> quota_cars -> freebusy_cars_vole; 637 freebusy_cars_vole -> schedule_across_quota; 638 639 cancel -> remove_from_quota_freebusy -> freebusy_cars_vole; 640 } 641 }}} 642 643 }}}}