Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
8 роки тому
10 роки тому
10 роки тому
8 роки тому
10 роки тому
7 роки тому
7 роки тому
10 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
10 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
8 роки тому
8 роки тому
8 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
7 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
5 роки тому
8 роки тому
10 роки тому
7 роки тому
9 роки тому
7 роки тому
9 роки тому
10 роки тому
10 роки тому
10 роки тому
6 роки тому
8 роки тому
10 роки тому
8 роки тому
10 роки тому
8 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
7 роки тому
10 роки тому
7 роки тому
7 роки тому
8 роки тому
5 роки тому
Restricted users (#6274) * Restricted users (#4334): initial implementation * Add User.IsRestricted & UI to edit it * Pass user object instead of user id to places where IsRestricted flag matters * Restricted users: maintain access rows for all referenced repos (incl public) * Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses * Add basic repo access tests for restricted users Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Mention restricted users in the faq Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Remove unnecessary `org.IsOrganization()` call Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert to an `int64` keyed `accessMap` * Add type `userAccess` * Add convenience func updateUserAccess() * Turn accessMap into a `map[int64]userAccess` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * or even better: `map[int64]*userAccess` * updateUserAccess(): use tighter syntax as suggested by lafriks * even tighter * Avoid extra loop * Don't disclose limited orgs to unauthenticated users * Don't assume block only applies to orgs * Use an array of `VisibleType` for filtering * fix yet another thinko * Ok - no need for u * Revert "Ok - no need for u" This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200. Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
4 роки тому
8 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
10 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
8 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
10 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
4 роки тому
7 роки тому
5 роки тому
5 роки тому
7 роки тому
9 роки тому
7 роки тому
7 роки тому
7 роки тому
7 роки тому
7 роки тому
7 роки тому
7 роки тому
Restricted users (#6274) * Restricted users (#4334): initial implementation * Add User.IsRestricted & UI to edit it * Pass user object instead of user id to places where IsRestricted flag matters * Restricted users: maintain access rows for all referenced repos (incl public) * Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses * Add basic repo access tests for restricted users Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Mention restricted users in the faq Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Remove unnecessary `org.IsOrganization()` call Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert to an `int64` keyed `accessMap` * Add type `userAccess` * Add convenience func updateUserAccess() * Turn accessMap into a `map[int64]userAccess` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * or even better: `map[int64]*userAccess` * updateUserAccess(): use tighter syntax as suggested by lafriks * even tighter * Avoid extra loop * Don't disclose limited orgs to unauthenticated users * Don't assume block only applies to orgs * Use an array of `VisibleType` for filtering * fix yet another thinko * Ok - no need for u * Revert "Ok - no need for u" This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200. Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
4 роки тому
Restricted users (#6274) * Restricted users (#4334): initial implementation * Add User.IsRestricted & UI to edit it * Pass user object instead of user id to places where IsRestricted flag matters * Restricted users: maintain access rows for all referenced repos (incl public) * Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses * Add basic repo access tests for restricted users Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Mention restricted users in the faq Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Remove unnecessary `org.IsOrganization()` call Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert to an `int64` keyed `accessMap` * Add type `userAccess` * Add convenience func updateUserAccess() * Turn accessMap into a `map[int64]userAccess` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * or even better: `map[int64]*userAccess` * updateUserAccess(): use tighter syntax as suggested by lafriks * even tighter * Avoid extra loop * Don't disclose limited orgs to unauthenticated users * Don't assume block only applies to orgs * Use an array of `VisibleType` for filtering * fix yet another thinko * Ok - no need for u * Revert "Ok - no need for u" This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200. Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
4 роки тому
Restricted users (#6274) * Restricted users (#4334): initial implementation * Add User.IsRestricted & UI to edit it * Pass user object instead of user id to places where IsRestricted flag matters * Restricted users: maintain access rows for all referenced repos (incl public) * Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses * Add basic repo access tests for restricted users Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Mention restricted users in the faq Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Remove unnecessary `org.IsOrganization()` call Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert to an `int64` keyed `accessMap` * Add type `userAccess` * Add convenience func updateUserAccess() * Turn accessMap into a `map[int64]userAccess` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * or even better: `map[int64]*userAccess` * updateUserAccess(): use tighter syntax as suggested by lafriks * even tighter * Avoid extra loop * Don't disclose limited orgs to unauthenticated users * Don't assume block only applies to orgs * Use an array of `VisibleType` for filtering * fix yet another thinko * Ok - no need for u * Revert "Ok - no need for u" This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200. Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
4 роки тому
Restricted users (#6274) * Restricted users (#4334): initial implementation * Add User.IsRestricted & UI to edit it * Pass user object instead of user id to places where IsRestricted flag matters * Restricted users: maintain access rows for all referenced repos (incl public) * Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses * Add basic repo access tests for restricted users Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Mention restricted users in the faq Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Remove unnecessary `org.IsOrganization()` call Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert to an `int64` keyed `accessMap` * Add type `userAccess` * Add convenience func updateUserAccess() * Turn accessMap into a `map[int64]userAccess` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * or even better: `map[int64]*userAccess` * updateUserAccess(): use tighter syntax as suggested by lafriks * even tighter * Avoid extra loop * Don't disclose limited orgs to unauthenticated users * Don't assume block only applies to orgs * Use an array of `VisibleType` for filtering * fix yet another thinko * Ok - no need for u * Revert "Ok - no need for u" This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200. Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
4 роки тому
7 роки тому
7 роки тому
7 роки тому
7 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package models
  6. import (
  7. "fmt"
  8. "os"
  9. "strings"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/setting"
  12. "code.gitea.io/gitea/modules/structs"
  13. "github.com/unknwon/com"
  14. "xorm.io/builder"
  15. "xorm.io/xorm"
  16. )
  17. // IsOwnedBy returns true if given user is in the owner team.
  18. func (org *User) IsOwnedBy(uid int64) (bool, error) {
  19. return IsOrganizationOwner(org.ID, uid)
  20. }
  21. // IsOrgMember returns true if given user is member of organization.
  22. func (org *User) IsOrgMember(uid int64) (bool, error) {
  23. return IsOrganizationMember(org.ID, uid)
  24. }
  25. // CanCreateOrgRepo returns true if given user can create repo in organization
  26. func (org *User) CanCreateOrgRepo(uid int64) (bool, error) {
  27. return CanCreateOrgRepo(org.ID, uid)
  28. }
  29. func (org *User) getTeam(e Engine, name string) (*Team, error) {
  30. return getTeam(e, org.ID, name)
  31. }
  32. // GetTeam returns named team of organization.
  33. func (org *User) GetTeam(name string) (*Team, error) {
  34. return org.getTeam(x, name)
  35. }
  36. func (org *User) getOwnerTeam(e Engine) (*Team, error) {
  37. return org.getTeam(e, ownerTeamName)
  38. }
  39. // GetOwnerTeam returns owner team of organization.
  40. func (org *User) GetOwnerTeam() (*Team, error) {
  41. return org.getOwnerTeam(x)
  42. }
  43. func (org *User) getTeams(e Engine) error {
  44. if org.Teams != nil {
  45. return nil
  46. }
  47. return e.
  48. Where("org_id=?", org.ID).
  49. OrderBy("CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END").
  50. Find(&org.Teams)
  51. }
  52. // GetTeams returns paginated teams that belong to organization.
  53. func (org *User) GetTeams(opts *SearchTeamOptions) error {
  54. if opts.Page != 0 {
  55. return org.getTeams(opts.getPaginatedSession())
  56. }
  57. return org.getTeams(x)
  58. }
  59. // GetMembers returns all members of organization.
  60. func (org *User) GetMembers() (err error) {
  61. org.Members, org.MembersIsPublic, err = FindOrgMembers(&FindOrgMembersOpts{
  62. OrgID: org.ID,
  63. })
  64. return
  65. }
  66. // FindOrgMembersOpts represensts find org members condtions
  67. type FindOrgMembersOpts struct {
  68. ListOptions
  69. OrgID int64
  70. PublicOnly bool
  71. }
  72. // CountOrgMembers counts the organization's members
  73. func CountOrgMembers(opts FindOrgMembersOpts) (int64, error) {
  74. sess := x.Where("org_id=?", opts.OrgID)
  75. if opts.PublicOnly {
  76. sess.And("is_public = ?", true)
  77. }
  78. return sess.Count(new(OrgUser))
  79. }
  80. // FindOrgMembers loads organization members according conditions
  81. func FindOrgMembers(opts *FindOrgMembersOpts) (UserList, map[int64]bool, error) {
  82. ous, err := GetOrgUsersByOrgID(opts)
  83. if err != nil {
  84. return nil, nil, err
  85. }
  86. var ids = make([]int64, len(ous))
  87. var idsIsPublic = make(map[int64]bool, len(ous))
  88. for i, ou := range ous {
  89. ids[i] = ou.UID
  90. idsIsPublic[ou.UID] = ou.IsPublic
  91. }
  92. users, err := GetUsersByIDs(ids)
  93. if err != nil {
  94. return nil, nil, err
  95. }
  96. return users, idsIsPublic, nil
  97. }
  98. // AddMember adds new member to organization.
  99. func (org *User) AddMember(uid int64) error {
  100. return AddOrgUser(org.ID, uid)
  101. }
  102. // RemoveMember removes member from organization.
  103. func (org *User) RemoveMember(uid int64) error {
  104. return RemoveOrgUser(org.ID, uid)
  105. }
  106. func (org *User) removeOrgRepo(e Engine, repoID int64) error {
  107. return removeOrgRepo(e, org.ID, repoID)
  108. }
  109. // RemoveOrgRepo removes all team-repository relations of organization.
  110. func (org *User) RemoveOrgRepo(repoID int64) error {
  111. return org.removeOrgRepo(x, repoID)
  112. }
  113. // CreateOrganization creates record of a new organization.
  114. func CreateOrganization(org, owner *User) (err error) {
  115. if !owner.CanCreateOrganization() {
  116. return ErrUserNotAllowedCreateOrg{}
  117. }
  118. if err = IsUsableUsername(org.Name); err != nil {
  119. return err
  120. }
  121. isExist, err := IsUserExist(0, org.Name)
  122. if err != nil {
  123. return err
  124. } else if isExist {
  125. return ErrUserAlreadyExist{org.Name}
  126. }
  127. org.LowerName = strings.ToLower(org.Name)
  128. if org.Rands, err = GetUserSalt(); err != nil {
  129. return err
  130. }
  131. if org.Salt, err = GetUserSalt(); err != nil {
  132. return err
  133. }
  134. org.UseCustomAvatar = true
  135. org.MaxRepoCreation = -1
  136. org.NumTeams = 1
  137. org.NumMembers = 1
  138. org.Type = UserTypeOrganization
  139. sess := x.NewSession()
  140. defer sess.Close()
  141. if err = sess.Begin(); err != nil {
  142. return err
  143. }
  144. if _, err = sess.Insert(org); err != nil {
  145. return fmt.Errorf("insert organization: %v", err)
  146. }
  147. if err = org.generateRandomAvatar(sess); err != nil {
  148. return fmt.Errorf("generate random avatar: %v", err)
  149. }
  150. // Add initial creator to organization and owner team.
  151. if _, err = sess.Insert(&OrgUser{
  152. UID: owner.ID,
  153. OrgID: org.ID,
  154. }); err != nil {
  155. return fmt.Errorf("insert org-user relation: %v", err)
  156. }
  157. // Create default owner team.
  158. t := &Team{
  159. OrgID: org.ID,
  160. LowerName: strings.ToLower(ownerTeamName),
  161. Name: ownerTeamName,
  162. Authorize: AccessModeOwner,
  163. NumMembers: 1,
  164. IncludesAllRepositories: true,
  165. CanCreateOrgRepo: true,
  166. }
  167. if _, err = sess.Insert(t); err != nil {
  168. return fmt.Errorf("insert owner team: %v", err)
  169. }
  170. // insert units for team
  171. var units = make([]TeamUnit, 0, len(AllRepoUnitTypes))
  172. for _, tp := range AllRepoUnitTypes {
  173. units = append(units, TeamUnit{
  174. OrgID: org.ID,
  175. TeamID: t.ID,
  176. Type: tp,
  177. })
  178. }
  179. if _, err = sess.Insert(&units); err != nil {
  180. if err := sess.Rollback(); err != nil {
  181. log.Error("CreateOrganization: sess.Rollback: %v", err)
  182. }
  183. return err
  184. }
  185. if _, err = sess.Insert(&TeamUser{
  186. UID: owner.ID,
  187. OrgID: org.ID,
  188. TeamID: t.ID,
  189. }); err != nil {
  190. return fmt.Errorf("insert team-user relation: %v", err)
  191. }
  192. return sess.Commit()
  193. }
  194. // GetOrgByName returns organization by given name.
  195. func GetOrgByName(name string) (*User, error) {
  196. if len(name) == 0 {
  197. return nil, ErrOrgNotExist{0, name}
  198. }
  199. u := &User{
  200. LowerName: strings.ToLower(name),
  201. Type: UserTypeOrganization,
  202. }
  203. has, err := x.Get(u)
  204. if err != nil {
  205. return nil, err
  206. } else if !has {
  207. return nil, ErrOrgNotExist{0, name}
  208. }
  209. return u, nil
  210. }
  211. // CountOrganizations returns number of organizations.
  212. func CountOrganizations() int64 {
  213. count, _ := x.
  214. Where("type=1").
  215. Count(new(User))
  216. return count
  217. }
  218. // DeleteOrganization completely and permanently deletes everything of organization.
  219. func DeleteOrganization(org *User) (err error) {
  220. if !org.IsOrganization() {
  221. return fmt.Errorf("%s is a user not an organization", org.Name)
  222. }
  223. sess := x.NewSession()
  224. defer sess.Close()
  225. if err = sess.Begin(); err != nil {
  226. return err
  227. }
  228. if err = deleteOrg(sess, org); err != nil {
  229. if IsErrUserOwnRepos(err) {
  230. return err
  231. } else if err != nil {
  232. return fmt.Errorf("deleteOrg: %v", err)
  233. }
  234. }
  235. return sess.Commit()
  236. }
  237. func deleteOrg(e *xorm.Session, u *User) error {
  238. // Check ownership of repository.
  239. count, err := getRepositoryCount(e, u)
  240. if err != nil {
  241. return fmt.Errorf("GetRepositoryCount: %v", err)
  242. } else if count > 0 {
  243. return ErrUserOwnRepos{UID: u.ID}
  244. }
  245. if err := deleteBeans(e,
  246. &Team{OrgID: u.ID},
  247. &OrgUser{OrgID: u.ID},
  248. &TeamUser{OrgID: u.ID},
  249. &TeamUnit{OrgID: u.ID},
  250. ); err != nil {
  251. return fmt.Errorf("deleteBeans: %v", err)
  252. }
  253. if _, err = e.ID(u.ID).Delete(new(User)); err != nil {
  254. return fmt.Errorf("Delete: %v", err)
  255. }
  256. // FIXME: system notice
  257. // Note: There are something just cannot be roll back,
  258. // so just keep error logs of those operations.
  259. path := UserPath(u.Name)
  260. if err := os.RemoveAll(path); err != nil {
  261. return fmt.Errorf("Failed to RemoveAll %s: %v", path, err)
  262. }
  263. if len(u.Avatar) > 0 {
  264. avatarPath := u.CustomAvatarPath()
  265. if com.IsExist(avatarPath) {
  266. if err := os.Remove(avatarPath); err != nil {
  267. return fmt.Errorf("Failed to remove %s: %v", avatarPath, err)
  268. }
  269. }
  270. }
  271. return nil
  272. }
  273. // ________ ____ ___
  274. // \_____ \_______ ____ | | \______ ___________
  275. // / | \_ __ \/ ___\| | / ___// __ \_ __ \
  276. // / | \ | \/ /_/ > | /\___ \\ ___/| | \/
  277. // \_______ /__| \___ /|______//____ >\___ >__|
  278. // \/ /_____/ \/ \/
  279. // OrgUser represents an organization-user relation.
  280. type OrgUser struct {
  281. ID int64 `xorm:"pk autoincr"`
  282. UID int64 `xorm:"INDEX UNIQUE(s)"`
  283. OrgID int64 `xorm:"INDEX UNIQUE(s)"`
  284. IsPublic bool `xorm:"INDEX"`
  285. }
  286. func isOrganizationOwner(e Engine, orgID, uid int64) (bool, error) {
  287. ownerTeam, err := getOwnerTeam(e, orgID)
  288. if err != nil {
  289. if IsErrTeamNotExist(err) {
  290. log.Error("Organization does not have owner team: %d", orgID)
  291. return false, nil
  292. }
  293. return false, err
  294. }
  295. return isTeamMember(e, orgID, ownerTeam.ID, uid)
  296. }
  297. // IsOrganizationOwner returns true if given user is in the owner team.
  298. func IsOrganizationOwner(orgID, uid int64) (bool, error) {
  299. return isOrganizationOwner(x, orgID, uid)
  300. }
  301. // IsOrganizationMember returns true if given user is member of organization.
  302. func IsOrganizationMember(orgID, uid int64) (bool, error) {
  303. return isOrganizationMember(x, orgID, uid)
  304. }
  305. func isOrganizationMember(e Engine, orgID, uid int64) (bool, error) {
  306. return e.
  307. Where("uid=?", uid).
  308. And("org_id=?", orgID).
  309. Table("org_user").
  310. Exist()
  311. }
  312. // IsPublicMembership returns true if given user public his/her membership.
  313. func IsPublicMembership(orgID, uid int64) (bool, error) {
  314. return x.
  315. Where("uid=?", uid).
  316. And("org_id=?", orgID).
  317. And("is_public=?", true).
  318. Table("org_user").
  319. Exist()
  320. }
  321. // CanCreateOrgRepo returns true if user can create repo in organization
  322. func CanCreateOrgRepo(orgID, uid int64) (bool, error) {
  323. if owner, err := IsOrganizationOwner(orgID, uid); owner || err != nil {
  324. return owner, err
  325. }
  326. return x.
  327. Where(builder.Eq{"team.can_create_org_repo": true}).
  328. Join("INNER", "team_user", "team_user.team_id = team.id").
  329. And("team_user.uid = ?", uid).
  330. And("team_user.org_id = ?", orgID).
  331. Exist(new(Team))
  332. }
  333. func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
  334. orgs := make([]*User, 0, 10)
  335. if !showAll {
  336. sess.And("`org_user`.is_public=?", true)
  337. }
  338. return orgs, sess.
  339. And("`org_user`.uid=?", userID).
  340. Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").
  341. Asc("`user`.name").
  342. Find(&orgs)
  343. }
  344. // GetOrgsByUserID returns a list of organizations that the given user ID
  345. // has joined.
  346. func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) {
  347. sess := x.NewSession()
  348. defer sess.Close()
  349. return getOrgsByUserID(sess, userID, showAll)
  350. }
  351. func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
  352. orgs := make([]*User, 0, 10)
  353. return orgs, sess.
  354. Join("INNER", "`team_user`", "`team_user`.org_id=`user`.id").
  355. Join("INNER", "`team`", "`team`.id=`team_user`.team_id").
  356. Where("`team_user`.uid=?", userID).
  357. And("`team`.authorize=?", AccessModeOwner).
  358. Asc("`user`.name").
  359. Find(&orgs)
  360. }
  361. // HasOrgVisible tells if the given user can see the given org
  362. func HasOrgVisible(org *User, user *User) bool {
  363. return hasOrgVisible(x, org, user)
  364. }
  365. func hasOrgVisible(e Engine, org *User, user *User) bool {
  366. // Not SignedUser
  367. if user == nil {
  368. return org.Visibility == structs.VisibleTypePublic
  369. }
  370. if user.IsAdmin {
  371. return true
  372. }
  373. if (org.Visibility == structs.VisibleTypePrivate || user.IsRestricted) && !org.isUserPartOfOrg(e, user.ID) {
  374. return false
  375. }
  376. return true
  377. }
  378. // HasOrgsVisible tells if the given user can see at least one of the orgs provided
  379. func HasOrgsVisible(orgs []*User, user *User) bool {
  380. if len(orgs) == 0 {
  381. return false
  382. }
  383. for _, org := range orgs {
  384. if HasOrgVisible(org, user) {
  385. return true
  386. }
  387. }
  388. return false
  389. }
  390. // GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID.
  391. func GetOwnedOrgsByUserID(userID int64) ([]*User, error) {
  392. sess := x.NewSession()
  393. defer sess.Close()
  394. return getOwnedOrgsByUserID(sess, userID)
  395. }
  396. // GetOwnedOrgsByUserIDDesc returns a list of organizations are owned by
  397. // given user ID, ordered descending by the given condition.
  398. func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
  399. return getOwnedOrgsByUserID(x.Desc(desc), userID)
  400. }
  401. // GetOrgsCanCreateRepoByUserID returns a list of organizations where given user ID
  402. // are allowed to create repos.
  403. func GetOrgsCanCreateRepoByUserID(userID int64) ([]*User, error) {
  404. orgs := make([]*User, 0, 10)
  405. return orgs, x.Join("INNER", "`team_user`", "`team_user`.org_id=`user`.id").
  406. Join("INNER", "`team`", "`team`.id=`team_user`.team_id").
  407. Where("`team_user`.uid=?", userID).
  408. And(builder.Eq{"`team`.authorize": AccessModeOwner}.Or(builder.Eq{"`team`.can_create_org_repo": true})).
  409. Desc("`user`.updated_unix").
  410. Find(&orgs)
  411. }
  412. // GetOrgUsersByUserID returns all organization-user relations by user ID.
  413. func GetOrgUsersByUserID(uid int64, opts *SearchOrganizationsOptions) ([]*OrgUser, error) {
  414. ous := make([]*OrgUser, 0, 10)
  415. sess := x.
  416. Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
  417. Where("`org_user`.uid=?", uid)
  418. if !opts.All {
  419. // Only show public organizations
  420. sess.And("is_public=?", true)
  421. }
  422. if opts.PageSize != 0 {
  423. sess = opts.setSessionPagination(sess)
  424. }
  425. err := sess.
  426. Asc("`user`.name").
  427. Find(&ous)
  428. return ous, err
  429. }
  430. // GetOrgUsersByOrgID returns all organization-user relations by organization ID.
  431. func GetOrgUsersByOrgID(opts *FindOrgMembersOpts) ([]*OrgUser, error) {
  432. return getOrgUsersByOrgID(x, opts)
  433. }
  434. func getOrgUsersByOrgID(e Engine, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
  435. sess := e.Where("org_id=?", opts.OrgID)
  436. if opts.PublicOnly {
  437. sess.And("is_public = ?", true)
  438. }
  439. if opts.ListOptions.PageSize > 0 {
  440. sess = opts.setSessionPagination(sess)
  441. ous := make([]*OrgUser, 0, opts.PageSize)
  442. return ous, sess.Find(&ous)
  443. }
  444. var ous []*OrgUser
  445. return ous, sess.Find(&ous)
  446. }
  447. // ChangeOrgUserStatus changes public or private membership status.
  448. func ChangeOrgUserStatus(orgID, uid int64, public bool) error {
  449. ou := new(OrgUser)
  450. has, err := x.
  451. Where("uid=?", uid).
  452. And("org_id=?", orgID).
  453. Get(ou)
  454. if err != nil {
  455. return err
  456. } else if !has {
  457. return nil
  458. }
  459. ou.IsPublic = public
  460. _, err = x.ID(ou.ID).Cols("is_public").Update(ou)
  461. return err
  462. }
  463. // AddOrgUser adds new user to given organization.
  464. func AddOrgUser(orgID, uid int64) error {
  465. isAlreadyMember, err := IsOrganizationMember(orgID, uid)
  466. if err != nil || isAlreadyMember {
  467. return err
  468. }
  469. sess := x.NewSession()
  470. defer sess.Close()
  471. if err := sess.Begin(); err != nil {
  472. return err
  473. }
  474. ou := &OrgUser{
  475. UID: uid,
  476. OrgID: orgID,
  477. IsPublic: setting.Service.DefaultOrgMemberVisible,
  478. }
  479. if _, err := sess.Insert(ou); err != nil {
  480. if err := sess.Rollback(); err != nil {
  481. log.Error("AddOrgUser: sess.Rollback: %v", err)
  482. }
  483. return err
  484. } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil {
  485. if err := sess.Rollback(); err != nil {
  486. log.Error("AddOrgUser: sess.Rollback: %v", err)
  487. }
  488. return err
  489. }
  490. return sess.Commit()
  491. }
  492. func removeOrgUser(sess *xorm.Session, orgID, userID int64) error {
  493. ou := new(OrgUser)
  494. has, err := sess.
  495. Where("uid=?", userID).
  496. And("org_id=?", orgID).
  497. Get(ou)
  498. if err != nil {
  499. return fmt.Errorf("get org-user: %v", err)
  500. } else if !has {
  501. return nil
  502. }
  503. org, err := getUserByID(sess, orgID)
  504. if err != nil {
  505. return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
  506. }
  507. // Check if the user to delete is the last member in owner team.
  508. if isOwner, err := isOrganizationOwner(sess, orgID, userID); err != nil {
  509. return err
  510. } else if isOwner {
  511. t, err := org.getOwnerTeam(sess)
  512. if err != nil {
  513. return err
  514. }
  515. if t.NumMembers == 1 {
  516. if err := t.getMembers(sess); err != nil {
  517. return err
  518. }
  519. if t.Members[0].ID == userID {
  520. return ErrLastOrgOwner{UID: userID}
  521. }
  522. }
  523. }
  524. if _, err := sess.ID(ou.ID).Delete(ou); err != nil {
  525. return err
  526. } else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgID); err != nil {
  527. return err
  528. }
  529. // Delete all repository accesses and unwatch them.
  530. env, err := org.accessibleReposEnv(sess, userID)
  531. if err != nil {
  532. return fmt.Errorf("AccessibleReposEnv: %v", err)
  533. }
  534. repoIDs, err := env.RepoIDs(1, org.NumRepos)
  535. if err != nil {
  536. return fmt.Errorf("GetUserRepositories [%d]: %v", userID, err)
  537. }
  538. for _, repoID := range repoIDs {
  539. if err = watchRepo(sess, userID, repoID, false); err != nil {
  540. return err
  541. }
  542. }
  543. if len(repoIDs) > 0 {
  544. if _, err = sess.
  545. Where("user_id = ?", userID).
  546. In("repo_id", repoIDs).
  547. Delete(new(Access)); err != nil {
  548. return err
  549. }
  550. }
  551. // Delete member in his/her teams.
  552. teams, err := getUserOrgTeams(sess, org.ID, userID)
  553. if err != nil {
  554. return err
  555. }
  556. for _, t := range teams {
  557. if err = removeTeamMember(sess, t, userID); err != nil {
  558. return err
  559. }
  560. }
  561. return nil
  562. }
  563. // RemoveOrgUser removes user from given organization.
  564. func RemoveOrgUser(orgID, userID int64) error {
  565. sess := x.NewSession()
  566. defer sess.Close()
  567. if err := sess.Begin(); err != nil {
  568. return err
  569. }
  570. if err := removeOrgUser(sess, orgID, userID); err != nil {
  571. return err
  572. }
  573. return sess.Commit()
  574. }
  575. func removeOrgRepo(e Engine, orgID, repoID int64) error {
  576. teamRepos := make([]*TeamRepo, 0, 10)
  577. if err := e.Find(&teamRepos, &TeamRepo{OrgID: orgID, RepoID: repoID}); err != nil {
  578. return err
  579. }
  580. if len(teamRepos) == 0 {
  581. return nil
  582. }
  583. if _, err := e.Delete(&TeamRepo{
  584. OrgID: orgID,
  585. RepoID: repoID,
  586. }); err != nil {
  587. return err
  588. }
  589. teamIDs := make([]int64, len(teamRepos))
  590. for i, teamRepo := range teamRepos {
  591. teamIDs[i] = teamRepo.TeamID
  592. }
  593. _, err := e.Decr("num_repos").In("id", teamIDs).Update(new(Team))
  594. return err
  595. }
  596. func (org *User) getUserTeams(e Engine, userID int64, cols ...string) ([]*Team, error) {
  597. teams := make([]*Team, 0, org.NumTeams)
  598. return teams, e.
  599. Where("`team_user`.org_id = ?", org.ID).
  600. Join("INNER", "team_user", "`team_user`.team_id = team.id").
  601. Join("INNER", "`user`", "`user`.id=team_user.uid").
  602. And("`team_user`.uid = ?", userID).
  603. Asc("`user`.name").
  604. Cols(cols...).
  605. Find(&teams)
  606. }
  607. func (org *User) getUserTeamIDs(e Engine, userID int64) ([]int64, error) {
  608. teamIDs := make([]int64, 0, org.NumTeams)
  609. return teamIDs, e.
  610. Table("team").
  611. Cols("team.id").
  612. Where("`team_user`.org_id = ?", org.ID).
  613. Join("INNER", "team_user", "`team_user`.team_id = team.id").
  614. And("`team_user`.uid = ?", userID).
  615. Find(&teamIDs)
  616. }
  617. // TeamsWithAccessToRepo returns all teamsthat have given access level to the repository.
  618. func (org *User) TeamsWithAccessToRepo(repoID int64, mode AccessMode) ([]*Team, error) {
  619. return GetTeamsWithAccessToRepo(org.ID, repoID, mode)
  620. }
  621. // GetUserTeamIDs returns of all team IDs of the organization that user is member of.
  622. func (org *User) GetUserTeamIDs(userID int64) ([]int64, error) {
  623. return org.getUserTeamIDs(x, userID)
  624. }
  625. // GetUserTeams returns all teams that belong to user,
  626. // and that the user has joined.
  627. func (org *User) GetUserTeams(userID int64) ([]*Team, error) {
  628. return org.getUserTeams(x, userID)
  629. }
  630. // AccessibleReposEnvironment operations involving the repositories that are
  631. // accessible to a particular user
  632. type AccessibleReposEnvironment interface {
  633. CountRepos() (int64, error)
  634. RepoIDs(page, pageSize int) ([]int64, error)
  635. Repos(page, pageSize int) ([]*Repository, error)
  636. MirrorRepos() ([]*Repository, error)
  637. AddKeyword(keyword string)
  638. SetSort(SearchOrderBy)
  639. }
  640. type accessibleReposEnv struct {
  641. org *User
  642. user *User
  643. teamIDs []int64
  644. e Engine
  645. keyword string
  646. orderBy SearchOrderBy
  647. }
  648. // AccessibleReposEnv an AccessibleReposEnvironment for the repositories in `org`
  649. // that are accessible to the specified user.
  650. func (org *User) AccessibleReposEnv(userID int64) (AccessibleReposEnvironment, error) {
  651. return org.accessibleReposEnv(x, userID)
  652. }
  653. func (org *User) accessibleReposEnv(e Engine, userID int64) (AccessibleReposEnvironment, error) {
  654. var user *User
  655. if userID > 0 {
  656. u, err := getUserByID(e, userID)
  657. if err != nil {
  658. return nil, err
  659. }
  660. user = u
  661. }
  662. teamIDs, err := org.getUserTeamIDs(e, userID)
  663. if err != nil {
  664. return nil, err
  665. }
  666. return &accessibleReposEnv{
  667. org: org,
  668. user: user,
  669. teamIDs: teamIDs,
  670. e: e,
  671. orderBy: SearchOrderByRecentUpdated,
  672. }, nil
  673. }
  674. func (env *accessibleReposEnv) cond() builder.Cond {
  675. var cond = builder.NewCond()
  676. if env.user == nil || !env.user.IsRestricted {
  677. cond = cond.Or(builder.Eq{
  678. "`repository`.owner_id": env.org.ID,
  679. "`repository`.is_private": false,
  680. })
  681. }
  682. if len(env.teamIDs) > 0 {
  683. cond = cond.Or(builder.In("team_repo.team_id", env.teamIDs))
  684. }
  685. if env.keyword != "" {
  686. cond = cond.And(builder.Like{"`repository`.lower_name", strings.ToLower(env.keyword)})
  687. }
  688. return cond
  689. }
  690. func (env *accessibleReposEnv) CountRepos() (int64, error) {
  691. repoCount, err := env.e.
  692. Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
  693. Where(env.cond()).
  694. Distinct("`repository`.id").
  695. Count(&Repository{})
  696. if err != nil {
  697. return 0, fmt.Errorf("count user repositories in organization: %v", err)
  698. }
  699. return repoCount, nil
  700. }
  701. func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
  702. if page <= 0 {
  703. page = 1
  704. }
  705. repoIDs := make([]int64, 0, pageSize)
  706. return repoIDs, env.e.
  707. Table("repository").
  708. Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
  709. Where(env.cond()).
  710. GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
  711. OrderBy(string(env.orderBy)).
  712. Limit(pageSize, (page-1)*pageSize).
  713. Cols("`repository`.id").
  714. Find(&repoIDs)
  715. }
  716. func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*Repository, error) {
  717. repoIDs, err := env.RepoIDs(page, pageSize)
  718. if err != nil {
  719. return nil, fmt.Errorf("GetUserRepositoryIDs: %v", err)
  720. }
  721. repos := make([]*Repository, 0, len(repoIDs))
  722. if len(repoIDs) == 0 {
  723. return repos, nil
  724. }
  725. return repos, env.e.
  726. In("`repository`.id", repoIDs).
  727. OrderBy(string(env.orderBy)).
  728. Find(&repos)
  729. }
  730. func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
  731. repoIDs := make([]int64, 0, 10)
  732. return repoIDs, env.e.
  733. Table("repository").
  734. Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
  735. Where(env.cond()).
  736. GroupBy("`repository`.id, `repository`.updated_unix").
  737. OrderBy(string(env.orderBy)).
  738. Cols("`repository`.id").
  739. Find(&repoIDs)
  740. }
  741. func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) {
  742. repoIDs, err := env.MirrorRepoIDs()
  743. if err != nil {
  744. return nil, fmt.Errorf("MirrorRepoIDs: %v", err)
  745. }
  746. repos := make([]*Repository, 0, len(repoIDs))
  747. if len(repoIDs) == 0 {
  748. return repos, nil
  749. }
  750. return repos, env.e.
  751. In("`repository`.id", repoIDs).
  752. Find(&repos)
  753. }
  754. func (env *accessibleReposEnv) AddKeyword(keyword string) {
  755. env.keyword = keyword
  756. }
  757. func (env *accessibleReposEnv) SetSort(orderBy SearchOrderBy) {
  758. env.orderBy = orderBy
  759. }