Fossil SCM
A new approach to sub-repos in which a specific user for the subrepo is specified in the CONFIG table entry.
Commit
e8b15ad642a681c4681cfa0ff7bac07535dcd883
Parent
4b545a8a0243c10…
2 files changed
+22
-47
+7
-6
+22
-47
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -631,55 +631,16 @@ | ||
| 631 | 631 | } |
| 632 | 632 | return rc; |
| 633 | 633 | } |
| 634 | 634 | |
| 635 | 635 | /* |
| 636 | -** For every character in zCap between 'a' and 'z' set a byte in seen[]. | |
| 637 | -*/ | |
| 638 | -static void setCap(const char *zCap, char *seen){ | |
| 639 | - int c; | |
| 640 | - if( zCap ){ | |
| 641 | - while( (c = *(zCap++))!=0 ){ | |
| 642 | - if( c>='a' && c<='z' ) seen[c-'a'] = 1; | |
| 643 | - } | |
| 644 | - } | |
| 645 | -} | |
| 646 | - | |
| 647 | -/* | |
| 648 | -** Remove privileges such that previleges are restricted to the | |
| 649 | -** set given in the argument. | |
| 650 | -*/ | |
| 651 | -void login_restrict_capabilities(const char *zAllowed){ | |
| 652 | - char zNew[30]; | |
| 653 | - char seen[26]; | |
| 654 | - int nNew = 0; | |
| 655 | - int i; | |
| 656 | - | |
| 657 | - /* Compute the intersection of current settings with zAllowed[] and | |
| 658 | - ** store the result in zNew[] | |
| 659 | - */ | |
| 660 | - memset(seen, 0, sizeof(seen)); | |
| 661 | - setCap(zAllowed, seen); | |
| 662 | - if( seen['v'-'a'] ){ | |
| 663 | - char *z = db_text(0, "SELECT cap FROM user WHERE login='developer'"); | |
| 664 | - setCap(z, seen); | |
| 665 | - fossil_free(z); | |
| 666 | - } | |
| 667 | - if( seen['u'-'a'] ){ | |
| 668 | - char *z = db_text(0, "SELECT cap FROM user WHERE login='reader'"); | |
| 669 | - setCap(z, seen); | |
| 670 | - fossil_free(z); | |
| 671 | - } | |
| 672 | - seen['u'-'a'] = 0; | |
| 673 | - seen['v'-'a'] = 0; | |
| 674 | - for(i=0; i<sizeof(seen); i++){ | |
| 675 | - char c = i+'a'; | |
| 676 | - if( seen[i] && login_has_capability(&c,1) ) zNew[nNew++] = i+'a'; | |
| 677 | - } | |
| 678 | - zNew[nNew] = 0; | |
| 679 | - | |
| 680 | - /* Turn off all capabilities */ | |
| 636 | +** Change the login to zUser. | |
| 637 | +*/ | |
| 638 | +void login_as_user(const char *zUser){ | |
| 639 | + char *zCap = ""; /* New capabilities */ | |
| 640 | + | |
| 641 | + /* Turn off all capabilities from prior logins */ | |
| 681 | 642 | g.okSetup = 0; |
| 682 | 643 | g.okAdmin = 0; |
| 683 | 644 | g.okDelete = 0; |
| 684 | 645 | g.okPassword = 0; |
| 685 | 646 | g.okQuery = 0; |
| @@ -699,12 +660,26 @@ | ||
| 699 | 660 | g.okTktFmt = 0; |
| 700 | 661 | g.okRdAddr = 0; |
| 701 | 662 | g.okZip = 0; |
| 702 | 663 | g.okPrivate = 0; |
| 703 | 664 | |
| 704 | - /* Set the reduced capabilities */ | |
| 705 | - login_set_capabilities(zNew); | |
| 665 | + /* Set the global variables recording the userid and login. The | |
| 666 | + ** "nobody" user is a special case in that g.zLogin==0. | |
| 667 | + */ | |
| 668 | + g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser); | |
| 669 | + if( g.userUid==0 ){ | |
| 670 | + zUser = 0; | |
| 671 | + g.userUid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); | |
| 672 | + } | |
| 673 | + if( g.userUid ){ | |
| 674 | + zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", g.userUid); | |
| 675 | + } | |
| 676 | + if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0; | |
| 677 | + g.zLogin = fossil_strdup(zUser); | |
| 678 | + | |
| 679 | + /* Set the capabilities */ | |
| 680 | + login_set_capabilities(zCap); | |
| 706 | 681 | login_anon_once = 1; |
| 707 | 682 | login_set_anon_nobody_capabilities(); |
| 708 | 683 | } |
| 709 | 684 | |
| 710 | 685 | /* |
| 711 | 686 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -631,55 +631,16 @@ | |
| 631 | } |
| 632 | return rc; |
| 633 | } |
| 634 | |
| 635 | /* |
| 636 | ** For every character in zCap between 'a' and 'z' set a byte in seen[]. |
| 637 | */ |
| 638 | static void setCap(const char *zCap, char *seen){ |
| 639 | int c; |
| 640 | if( zCap ){ |
| 641 | while( (c = *(zCap++))!=0 ){ |
| 642 | if( c>='a' && c<='z' ) seen[c-'a'] = 1; |
| 643 | } |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | /* |
| 648 | ** Remove privileges such that previleges are restricted to the |
| 649 | ** set given in the argument. |
| 650 | */ |
| 651 | void login_restrict_capabilities(const char *zAllowed){ |
| 652 | char zNew[30]; |
| 653 | char seen[26]; |
| 654 | int nNew = 0; |
| 655 | int i; |
| 656 | |
| 657 | /* Compute the intersection of current settings with zAllowed[] and |
| 658 | ** store the result in zNew[] |
| 659 | */ |
| 660 | memset(seen, 0, sizeof(seen)); |
| 661 | setCap(zAllowed, seen); |
| 662 | if( seen['v'-'a'] ){ |
| 663 | char *z = db_text(0, "SELECT cap FROM user WHERE login='developer'"); |
| 664 | setCap(z, seen); |
| 665 | fossil_free(z); |
| 666 | } |
| 667 | if( seen['u'-'a'] ){ |
| 668 | char *z = db_text(0, "SELECT cap FROM user WHERE login='reader'"); |
| 669 | setCap(z, seen); |
| 670 | fossil_free(z); |
| 671 | } |
| 672 | seen['u'-'a'] = 0; |
| 673 | seen['v'-'a'] = 0; |
| 674 | for(i=0; i<sizeof(seen); i++){ |
| 675 | char c = i+'a'; |
| 676 | if( seen[i] && login_has_capability(&c,1) ) zNew[nNew++] = i+'a'; |
| 677 | } |
| 678 | zNew[nNew] = 0; |
| 679 | |
| 680 | /* Turn off all capabilities */ |
| 681 | g.okSetup = 0; |
| 682 | g.okAdmin = 0; |
| 683 | g.okDelete = 0; |
| 684 | g.okPassword = 0; |
| 685 | g.okQuery = 0; |
| @@ -699,12 +660,26 @@ | |
| 699 | g.okTktFmt = 0; |
| 700 | g.okRdAddr = 0; |
| 701 | g.okZip = 0; |
| 702 | g.okPrivate = 0; |
| 703 | |
| 704 | /* Set the reduced capabilities */ |
| 705 | login_set_capabilities(zNew); |
| 706 | login_anon_once = 1; |
| 707 | login_set_anon_nobody_capabilities(); |
| 708 | } |
| 709 | |
| 710 | /* |
| 711 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -631,55 +631,16 @@ | |
| 631 | } |
| 632 | return rc; |
| 633 | } |
| 634 | |
| 635 | /* |
| 636 | ** Change the login to zUser. |
| 637 | */ |
| 638 | void login_as_user(const char *zUser){ |
| 639 | char *zCap = ""; /* New capabilities */ |
| 640 | |
| 641 | /* Turn off all capabilities from prior logins */ |
| 642 | g.okSetup = 0; |
| 643 | g.okAdmin = 0; |
| 644 | g.okDelete = 0; |
| 645 | g.okPassword = 0; |
| 646 | g.okQuery = 0; |
| @@ -699,12 +660,26 @@ | |
| 660 | g.okTktFmt = 0; |
| 661 | g.okRdAddr = 0; |
| 662 | g.okZip = 0; |
| 663 | g.okPrivate = 0; |
| 664 | |
| 665 | /* Set the global variables recording the userid and login. The |
| 666 | ** "nobody" user is a special case in that g.zLogin==0. |
| 667 | */ |
| 668 | g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser); |
| 669 | if( g.userUid==0 ){ |
| 670 | zUser = 0; |
| 671 | g.userUid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| 672 | } |
| 673 | if( g.userUid ){ |
| 674 | zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", g.userUid); |
| 675 | } |
| 676 | if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0; |
| 677 | g.zLogin = fossil_strdup(zUser); |
| 678 | |
| 679 | /* Set the capabilities */ |
| 680 | login_set_capabilities(zCap); |
| 681 | login_anon_once = 1; |
| 682 | login_set_anon_nobody_capabilities(); |
| 683 | } |
| 684 | |
| 685 | /* |
| 686 |
+7
-6
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -983,35 +983,36 @@ | ||
| 983 | 983 | |
| 984 | 984 | /* Look for sub-repositories. A sub-repository is another repository |
| 985 | 985 | ** that accepts the login credentials of the current repository. A |
| 986 | 986 | ** subrepository is identified by a CONFIG table entry "subrepo:NAME" |
| 987 | 987 | ** where NAME is the first component of the path. The value of the |
| 988 | - ** the CONFIG entries is the string "CAP:FILENAME" where CAP is the | |
| 989 | - ** maximum capability string and FILENAME is the new repository | |
| 990 | - ** filename. | |
| 988 | + ** the CONFIG entries is the string "USER:FILENAME" where USER is the | |
| 989 | + ** USER name to log in as in the subrepository and FILENAME is the | |
| 990 | + ** repository filename. | |
| 991 | 991 | */ |
| 992 | 992 | zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'", |
| 993 | 993 | g.zPath); |
| 994 | 994 | if( zAltRepo ){ |
| 995 | 995 | int nHost; |
| 996 | 996 | int jj; |
| 997 | - char *zInheritCap = zAltRepo; | |
| 997 | + char *zUser = zAltRepo; | |
| 998 | 998 | login_check_credentials(); |
| 999 | 999 | for(jj=0; zAltRepo[jj] && zAltRepo[jj]!=':'; jj++){} |
| 1000 | 1000 | if( zAltRepo[jj]==':' ){ |
| 1001 | 1001 | zAltRepo[jj] = 0; |
| 1002 | 1002 | zAltRepo += jj+1; |
| 1003 | 1003 | }else{ |
| 1004 | - zInheritCap = ""; | |
| 1004 | + zUser = "nobody"; | |
| 1005 | 1005 | } |
| 1006 | 1006 | if( zAltRepo[0]!='/' ){ |
| 1007 | 1007 | zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo); |
| 1008 | 1008 | file_simplify_name(zAltRepo, -1); |
| 1009 | 1009 | } |
| 1010 | 1010 | db_close(1); |
| 1011 | 1011 | db_open_repository(zAltRepo); |
| 1012 | - login_restrict_capabilities(zInheritCap); | |
| 1012 | + login_as_user(zUser); | |
| 1013 | + g.okPassword = 0; | |
| 1013 | 1014 | zPath += i; |
| 1014 | 1015 | nHost = g.zTop - g.zBaseURL; |
| 1015 | 1016 | g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath); |
| 1016 | 1017 | g.zTop = g.zBaseURL + nHost; |
| 1017 | 1018 | continue; |
| 1018 | 1019 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -983,35 +983,36 @@ | |
| 983 | |
| 984 | /* Look for sub-repositories. A sub-repository is another repository |
| 985 | ** that accepts the login credentials of the current repository. A |
| 986 | ** subrepository is identified by a CONFIG table entry "subrepo:NAME" |
| 987 | ** where NAME is the first component of the path. The value of the |
| 988 | ** the CONFIG entries is the string "CAP:FILENAME" where CAP is the |
| 989 | ** maximum capability string and FILENAME is the new repository |
| 990 | ** filename. |
| 991 | */ |
| 992 | zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'", |
| 993 | g.zPath); |
| 994 | if( zAltRepo ){ |
| 995 | int nHost; |
| 996 | int jj; |
| 997 | char *zInheritCap = zAltRepo; |
| 998 | login_check_credentials(); |
| 999 | for(jj=0; zAltRepo[jj] && zAltRepo[jj]!=':'; jj++){} |
| 1000 | if( zAltRepo[jj]==':' ){ |
| 1001 | zAltRepo[jj] = 0; |
| 1002 | zAltRepo += jj+1; |
| 1003 | }else{ |
| 1004 | zInheritCap = ""; |
| 1005 | } |
| 1006 | if( zAltRepo[0]!='/' ){ |
| 1007 | zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo); |
| 1008 | file_simplify_name(zAltRepo, -1); |
| 1009 | } |
| 1010 | db_close(1); |
| 1011 | db_open_repository(zAltRepo); |
| 1012 | login_restrict_capabilities(zInheritCap); |
| 1013 | zPath += i; |
| 1014 | nHost = g.zTop - g.zBaseURL; |
| 1015 | g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath); |
| 1016 | g.zTop = g.zBaseURL + nHost; |
| 1017 | continue; |
| 1018 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -983,35 +983,36 @@ | |
| 983 | |
| 984 | /* Look for sub-repositories. A sub-repository is another repository |
| 985 | ** that accepts the login credentials of the current repository. A |
| 986 | ** subrepository is identified by a CONFIG table entry "subrepo:NAME" |
| 987 | ** where NAME is the first component of the path. The value of the |
| 988 | ** the CONFIG entries is the string "USER:FILENAME" where USER is the |
| 989 | ** USER name to log in as in the subrepository and FILENAME is the |
| 990 | ** repository filename. |
| 991 | */ |
| 992 | zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'", |
| 993 | g.zPath); |
| 994 | if( zAltRepo ){ |
| 995 | int nHost; |
| 996 | int jj; |
| 997 | char *zUser = zAltRepo; |
| 998 | login_check_credentials(); |
| 999 | for(jj=0; zAltRepo[jj] && zAltRepo[jj]!=':'; jj++){} |
| 1000 | if( zAltRepo[jj]==':' ){ |
| 1001 | zAltRepo[jj] = 0; |
| 1002 | zAltRepo += jj+1; |
| 1003 | }else{ |
| 1004 | zUser = "nobody"; |
| 1005 | } |
| 1006 | if( zAltRepo[0]!='/' ){ |
| 1007 | zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo); |
| 1008 | file_simplify_name(zAltRepo, -1); |
| 1009 | } |
| 1010 | db_close(1); |
| 1011 | db_open_repository(zAltRepo); |
| 1012 | login_as_user(zUser); |
| 1013 | g.okPassword = 0; |
| 1014 | zPath += i; |
| 1015 | nHost = g.zTop - g.zBaseURL; |
| 1016 | g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath); |
| 1017 | g.zTop = g.zBaseURL + nHost; |
| 1018 | continue; |
| 1019 |