Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
Move macaron to chi (#14293) Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR. - [x] Define `context.ResponseWriter` interface with an implementation `context.Response`. - [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before. - [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic . - [x] Use https://github.com/unrolled/render instead of macaron's internal render - [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip - [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK** - [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha - [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache - [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding - [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors - [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation` - [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle. - [x] Removed macaron log service because it's not need any more. **BREAK** - [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition. - [x] Move Git HTTP protocol implementation to use routers directly. - [x] Fix the problem that chi routes don't support trailing slash but macaron did. - [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render. Notices: - Chi router don't support request with trailing slash - Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI. Co-authored-by: 6543 <6543@obermui.de>
3 лет назад
Move macaron to chi (#14293) Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR. - [x] Define `context.ResponseWriter` interface with an implementation `context.Response`. - [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before. - [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic . - [x] Use https://github.com/unrolled/render instead of macaron's internal render - [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip - [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK** - [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha - [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache - [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding - [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors - [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation` - [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle. - [x] Removed macaron log service because it's not need any more. **BREAK** - [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition. - [x] Move Git HTTP protocol implementation to use routers directly. - [x] Fix the problem that chi routes don't support trailing slash but macaron did. - [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render. Notices: - Chi router don't support request with trailing slash - Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI. Co-authored-by: 6543 <6543@obermui.de>
3 лет назад
Move macaron to chi (#14293) Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR. - [x] Define `context.ResponseWriter` interface with an implementation `context.Response`. - [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before. - [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic . - [x] Use https://github.com/unrolled/render instead of macaron's internal render - [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip - [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK** - [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha - [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache - [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding - [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors - [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation` - [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle. - [x] Removed macaron log service because it's not need any more. **BREAK** - [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition. - [x] Move Git HTTP protocol implementation to use routers directly. - [x] Fix the problem that chi routes don't support trailing slash but macaron did. - [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render. Notices: - Chi router don't support request with trailing slash - Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI. Co-authored-by: 6543 <6543@obermui.de>
3 лет назад
Refactor path & config system (#25330) # The problem There were many "path tricks": * By default, Gitea uses its program directory as its work path * Gitea tries to use the "work path" to guess its "custom path" and "custom conf (app.ini)" * Users might want to use other directories as work path * The non-default work path should be passed to Gitea by GITEA_WORK_DIR or "--work-path" * But some Gitea processes are started without these values * The "serv" process started by OpenSSH server * The CLI sub-commands started by site admin * The paths are guessed by SetCustomPathAndConf again and again * The default values of "work path / custom path / custom conf" can be changed when compiling # The solution * Use `InitWorkPathAndCommonConfig` to handle these path tricks, and use test code to cover its behaviors. * When Gitea's web server runs, write the WORK_PATH to "app.ini", this value must be the most correct one, because if this value is not right, users would find that the web UI doesn't work and then they should be able to fix it. * Then all other sub-commands can use the WORK_PATH in app.ini to initialize their paths. * By the way, when Gitea starts for git protocol, it shouldn't output any log, otherwise the git protocol gets broken and client blocks forever. The "work path" priority is: WORK_PATH in app.ini > cmd arg --work-path > env var GITEA_WORK_DIR > builtin default The "app.ini" searching order is: cmd arg --config > cmd arg "work path / custom path" > env var "work path / custom path" > builtin default ## ⚠️ BREAKING If your instance's "work path / custom path / custom conf" doesn't meet the requirements (eg: work path must be absolute), Gitea will report a fatal error and exit. You need to set these values according to the error log. ---- Close #24818 Close #24222 Close #21606 Close #21498 Close #25107 Close #24981 Maybe close #24503 Replace #23301 Replace #22754 And maybe more
11 месяцев назад
Move macaron to chi (#14293) Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR. - [x] Define `context.ResponseWriter` interface with an implementation `context.Response`. - [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before. - [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic . - [x] Use https://github.com/unrolled/render instead of macaron's internal render - [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip - [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK** - [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha - [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache - [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding - [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors - [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation` - [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle. - [x] Removed macaron log service because it's not need any more. **BREAK** - [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition. - [x] Move Git HTTP protocol implementation to use routers directly. - [x] Fix the problem that chi routes don't support trailing slash but macaron did. - [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render. Notices: - Chi router don't support request with trailing slash - Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI. Co-authored-by: 6543 <6543@obermui.de>
3 лет назад
10 лет назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
8 лет назад
8 лет назад
8 лет назад
8 лет назад
10 лет назад
7 лет назад
8 лет назад
10 лет назад
8 лет назад
8 лет назад
8 лет назад
8 лет назад
Feature: Timetracking (#2211) * Added comment's hashtag to url for mail notifications. * Added explanation to return statement + documentation. * Replacing in-line link generation with HTMLURL. (+gofmt) * Replaced action-based model with nil-based model. (+gofmt) * Replaced mailIssueActionToParticipants with mailIssueCommentToParticipants. * Updating comment for mailIssueCommentToParticipants * Added link to comment in "Dashboard" * Deleting feed entry if a comment is going to be deleted * Added migration * Added improved migration to add a CommentID column to action. * Added improved links to comments in feed entries. * Fixes #1956 by filtering for deleted comments that are referenced in actions. * Introducing "IsDeleted" column to action. * Adding design draft (not functional) * Adding database models for stopwatches and trackedtimes * See go-gitea/gitea#967 * Adding design draft (not functional) * Adding translations and improving design * Implementing stopwatch (for timetracking) * Make UI functional * Add hints in timeline for time tracking events * Implementing timetracking feature * Adding "Add time manual" option * Improved stopwatch * Created report of total spent time by user * Only showing total time spent if theire is something to show. * Adding license headers. * Improved error handling for "Add Time Manual" * Adding @sapks 's changes, refactoring * Adding API for feature tracking * Adding unit test * Adding DISABLE/ENABLE option to Repository settings page * Improving translations * Applying @sapk 's changes * Removing repo_unit and using IssuesSetting for disabling/enabling timetracker * Adding DEFAULT_ENABLE_TIMETRACKER to config, installation and admin menu * Improving documentation * Fixing vendor/ folder * Changing timtracking routes by adding subgroups /times and /times/stopwatch (Proposed by @lafriks ) * Restricting write access to timetracking based on the repo settings (Proposed by @lafriks ) * Fixed minor permissions bug. * Adding CanUseTimetracker and IsTimetrackerEnabled in ctx.Repo * Allow assignees and authors to track there time too. * Fixed some build-time-errors + logical errors. * Removing unused Get...ByID functions * Moving IsTimetrackerEnabled from context.Repository to models.Repository * Adding a seperate file for issue related repo functions * Adding license headers * Fixed GetUserByParams return 404 * Moving /users/:username/times to /repos/:username/:reponame/times/:username for security reasons * Adding /repos/:username/times to get all tracked times of the repo * Updating sdk-dependency * Updating swagger.v1.json * Adding warning if user has already a running stopwatch (auto-timetracker) * Replacing GetTrackedTimesBy... with GetTrackedTimes(options FindTrackedTimesOptions) * Changing code.gitea.io/sdk back to code.gitea.io/sdk * Correcting spelling mistake * Updating vendor.json * Changing GET stopwatch/toggle to POST stopwatch/toggle * Changing GET stopwatch/cancel to POST stopwatch/cancel * Added migration for stopwatches/timetracking * Fixed some access bugs for read-only users * Added default allow only contributors to track time value to config * Fixed migration by chaging x.Iterate to x.Find * Resorted imports * Moved Add Time Manually form to repo_form.go * Removed "Seconds" field from Add Time Manually * Resorted imports * Improved permission checking * Fixed some bugs * Added integration test * gofmt * Adding integration test by @lafriks * Added created_unix to comment fixtures * Using last event instead of a fixed event * Adding another integration test by @lafriks * Fixing bug Timetracker enabled causing error 500 at sidebar.tpl * Fixed a refactoring bug that resulted in hiding "HasUserStopwatch" warning. * Returning TrackedTime instead of AddTimeOption at AddTime. * Updating SDK from go-gitea/go-sdk#69 * Resetting Go-SDK back to default repository * Fixing test-vendor by changing ini back to original repository * Adding "tags" to swagger spec * govendor sync * Removed duplicate * Formatting templates * Adding IsTimetrackingEnabled checks to API * Improving translations / english texts * Improving documentation * Updating swagger spec * Fixing integration test caused be translation-changes * Removed encoding issues in local_en-US.ini. * "Added" copyright line * Moved unit.IssuesConfig().EnableTimetracker into a != nil check * Removed some other encoding issues in local_en-US.ini * Improved javascript by checking if data-context exists * Replaced manual comment creation with CreateComment * Removed unnecessary code * Improved error checking * Small cosmetic changes * Replaced int>string>duration parsing with int>duration parsing * Fixed encoding issues * Removed unused imports Signed-off-by: Jonas Franz <info@jonasfranz.software>
6 лет назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
10 лет назад
10 лет назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
10 лет назад
10 лет назад
8 лет назад
8 лет назад
9 лет назад
Git LFS support v2 (#122) * Import github.com/git-lfs/lfs-test-server as lfs module base Imported commit is 3968aac269a77b73924649b9412ae03f7ccd3198 Removed: Dockerfile CONTRIBUTING.md mgmt* script/ vendor/ kvlogger.go .dockerignore .gitignore README.md * Remove config, add JWT support from github.com/mgit-at/lfs-test-server Imported commit f0cdcc5a01599c5a955dc1bbf683bb4acecdba83 * Add LFS settings * Add LFS meta object model * Add LFS routes and initialization * Import github.com/dgrijalva/jwt-go into vendor/ * Adapt LFS module: handlers, routing, meta store * Move LFS routes to /user/repo/info/lfs/* * Add request header checks to LFS BatchHandler / PostHandler * Implement LFS basic authentication * Rework JWT secret generation / load * Implement LFS SSH token authentication with JWT Specification: https://github.com/github/git-lfs/tree/master/docs/api * Integrate LFS settings into install process * Remove LFS objects when repository is deleted Only removes objects from content store when deleted repo is the only referencing repository * Make LFS module stateless Fixes bug where LFS would not work after installation without restarting Gitea * Change 500 'Internal Server Error' to 400 'Bad Request' * Change sql query to xorm call * Remove unneeded type from LFS module * Change internal imports to code.gitea.io/gitea/ * Add Gitea authors copyright * Change basic auth realm to "gitea-lfs" * Add unique indexes to LFS model * Use xorm count function in LFS check on repository delete * Return io.ReadCloser from content store and close after usage * Add LFS info to runWeb() * Export LFS content store base path * LFS file download from UI * Work around git-lfs client issue with unauthenticated requests Returning a dummy Authorization header for unauthenticated requests lets git-lfs client skip asking for auth credentials See: https://github.com/github/git-lfs/issues/1088 * Fix unauthenticated UI downloads from public repositories * Authentication check order, Finish LFS file view logic * Ignore LFS hooks if installed for current OS user Fixes Gitea UI actions for repositories tracking LFS files. Checks for minimum needed git version by parsing the semantic version string. * Hide LFS metafile diff from commit view, marking as binary * Show LFS notice if file in commit view is tracked * Add notbefore/nbf JWT claim * Correct lint suggestions - comments for structs and functions - Add comments to LFS model - Function comment for GetRandomBytesAsBase64 - LFS server function comments and lint variable suggestion * Move secret generation code out of conditional Ensures no LFS code may run with an empty secret * Do not hand out JWT tokens if LFS server support is disabled
7 лет назад
Git LFS support v2 (#122) * Import github.com/git-lfs/lfs-test-server as lfs module base Imported commit is 3968aac269a77b73924649b9412ae03f7ccd3198 Removed: Dockerfile CONTRIBUTING.md mgmt* script/ vendor/ kvlogger.go .dockerignore .gitignore README.md * Remove config, add JWT support from github.com/mgit-at/lfs-test-server Imported commit f0cdcc5a01599c5a955dc1bbf683bb4acecdba83 * Add LFS settings * Add LFS meta object model * Add LFS routes and initialization * Import github.com/dgrijalva/jwt-go into vendor/ * Adapt LFS module: handlers, routing, meta store * Move LFS routes to /user/repo/info/lfs/* * Add request header checks to LFS BatchHandler / PostHandler * Implement LFS basic authentication * Rework JWT secret generation / load * Implement LFS SSH token authentication with JWT Specification: https://github.com/github/git-lfs/tree/master/docs/api * Integrate LFS settings into install process * Remove LFS objects when repository is deleted Only removes objects from content store when deleted repo is the only referencing repository * Make LFS module stateless Fixes bug where LFS would not work after installation without restarting Gitea * Change 500 'Internal Server Error' to 400 'Bad Request' * Change sql query to xorm call * Remove unneeded type from LFS module * Change internal imports to code.gitea.io/gitea/ * Add Gitea authors copyright * Change basic auth realm to "gitea-lfs" * Add unique indexes to LFS model * Use xorm count function in LFS check on repository delete * Return io.ReadCloser from content store and close after usage * Add LFS info to runWeb() * Export LFS content store base path * LFS file download from UI * Work around git-lfs client issue with unauthenticated requests Returning a dummy Authorization header for unauthenticated requests lets git-lfs client skip asking for auth credentials See: https://github.com/github/git-lfs/issues/1088 * Fix unauthenticated UI downloads from public repositories * Authentication check order, Finish LFS file view logic * Ignore LFS hooks if installed for current OS user Fixes Gitea UI actions for repositories tracking LFS files. Checks for minimum needed git version by parsing the semantic version string. * Hide LFS metafile diff from commit view, marking as binary * Show LFS notice if file in commit view is tracked * Add notbefore/nbf JWT claim * Correct lint suggestions - comments for structs and functions - Add comments to LFS model - Function comment for GetRandomBytesAsBase64 - LFS server function comments and lint variable suggestion * Move secret generation code out of conditional Ensures no LFS code may run with an empty secret * Do not hand out JWT tokens if LFS server support is disabled
7 лет назад
9 лет назад
8 лет назад
8 лет назад
10 лет назад
Refactor path & config system (#25330) # The problem There were many "path tricks": * By default, Gitea uses its program directory as its work path * Gitea tries to use the "work path" to guess its "custom path" and "custom conf (app.ini)" * Users might want to use other directories as work path * The non-default work path should be passed to Gitea by GITEA_WORK_DIR or "--work-path" * But some Gitea processes are started without these values * The "serv" process started by OpenSSH server * The CLI sub-commands started by site admin * The paths are guessed by SetCustomPathAndConf again and again * The default values of "work path / custom path / custom conf" can be changed when compiling # The solution * Use `InitWorkPathAndCommonConfig` to handle these path tricks, and use test code to cover its behaviors. * When Gitea's web server runs, write the WORK_PATH to "app.ini", this value must be the most correct one, because if this value is not right, users would find that the web UI doesn't work and then they should be able to fix it. * Then all other sub-commands can use the WORK_PATH in app.ini to initialize their paths. * By the way, when Gitea starts for git protocol, it shouldn't output any log, otherwise the git protocol gets broken and client blocks forever. The "work path" priority is: WORK_PATH in app.ini > cmd arg --work-path > env var GITEA_WORK_DIR > builtin default The "app.ini" searching order is: cmd arg --config > cmd arg "work path / custom path" > env var "work path / custom path" > builtin default ## ⚠️ BREAKING If your instance's "work path / custom path / custom conf" doesn't meet the requirements (eg: work path must be absolute), Gitea will report a fatal error and exit. You need to set these values according to the error log. ---- Close #24818 Close #24222 Close #21606 Close #21498 Close #25107 Close #24981 Maybe close #24503 Replace #23301 Replace #22754 And maybe more
11 месяцев назад
Refactor path & config system (#25330) # The problem There were many "path tricks": * By default, Gitea uses its program directory as its work path * Gitea tries to use the "work path" to guess its "custom path" and "custom conf (app.ini)" * Users might want to use other directories as work path * The non-default work path should be passed to Gitea by GITEA_WORK_DIR or "--work-path" * But some Gitea processes are started without these values * The "serv" process started by OpenSSH server * The CLI sub-commands started by site admin * The paths are guessed by SetCustomPathAndConf again and again * The default values of "work path / custom path / custom conf" can be changed when compiling # The solution * Use `InitWorkPathAndCommonConfig` to handle these path tricks, and use test code to cover its behaviors. * When Gitea's web server runs, write the WORK_PATH to "app.ini", this value must be the most correct one, because if this value is not right, users would find that the web UI doesn't work and then they should be able to fix it. * Then all other sub-commands can use the WORK_PATH in app.ini to initialize their paths. * By the way, when Gitea starts for git protocol, it shouldn't output any log, otherwise the git protocol gets broken and client blocks forever. The "work path" priority is: WORK_PATH in app.ini > cmd arg --work-path > env var GITEA_WORK_DIR > builtin default The "app.ini" searching order is: cmd arg --config > cmd arg "work path / custom path" > env var "work path / custom path" > builtin default ## ⚠️ BREAKING If your instance's "work path / custom path / custom conf" doesn't meet the requirements (eg: work path must be absolute), Gitea will report a fatal error and exit. You need to set these values according to the error log. ---- Close #24818 Close #24222 Close #21606 Close #21498 Close #25107 Close #24981 Maybe close #24503 Replace #23301 Replace #22754 And maybe more
11 месяцев назад
Git LFS support v2 (#122) * Import github.com/git-lfs/lfs-test-server as lfs module base Imported commit is 3968aac269a77b73924649b9412ae03f7ccd3198 Removed: Dockerfile CONTRIBUTING.md mgmt* script/ vendor/ kvlogger.go .dockerignore .gitignore README.md * Remove config, add JWT support from github.com/mgit-at/lfs-test-server Imported commit f0cdcc5a01599c5a955dc1bbf683bb4acecdba83 * Add LFS settings * Add LFS meta object model * Add LFS routes and initialization * Import github.com/dgrijalva/jwt-go into vendor/ * Adapt LFS module: handlers, routing, meta store * Move LFS routes to /user/repo/info/lfs/* * Add request header checks to LFS BatchHandler / PostHandler * Implement LFS basic authentication * Rework JWT secret generation / load * Implement LFS SSH token authentication with JWT Specification: https://github.com/github/git-lfs/tree/master/docs/api * Integrate LFS settings into install process * Remove LFS objects when repository is deleted Only removes objects from content store when deleted repo is the only referencing repository * Make LFS module stateless Fixes bug where LFS would not work after installation without restarting Gitea * Change 500 'Internal Server Error' to 400 'Bad Request' * Change sql query to xorm call * Remove unneeded type from LFS module * Change internal imports to code.gitea.io/gitea/ * Add Gitea authors copyright * Change basic auth realm to "gitea-lfs" * Add unique indexes to LFS model * Use xorm count function in LFS check on repository delete * Return io.ReadCloser from content store and close after usage * Add LFS info to runWeb() * Export LFS content store base path * LFS file download from UI * Work around git-lfs client issue with unauthenticated requests Returning a dummy Authorization header for unauthenticated requests lets git-lfs client skip asking for auth credentials See: https://github.com/github/git-lfs/issues/1088 * Fix unauthenticated UI downloads from public repositories * Authentication check order, Finish LFS file view logic * Ignore LFS hooks if installed for current OS user Fixes Gitea UI actions for repositories tracking LFS files. Checks for minimum needed git version by parsing the semantic version string. * Hide LFS metafile diff from commit view, marking as binary * Show LFS notice if file in commit view is tracked * Add notbefore/nbf JWT claim * Correct lint suggestions - comments for structs and functions - Add comments to LFS model - Function comment for GetRandomBytesAsBase64 - LFS server function comments and lint variable suggestion * Move secret generation code out of conditional Ensures no LFS code may run with an empty secret * Do not hand out JWT tokens if LFS server support is disabled
7 лет назад
Git LFS support v2 (#122) * Import github.com/git-lfs/lfs-test-server as lfs module base Imported commit is 3968aac269a77b73924649b9412ae03f7ccd3198 Removed: Dockerfile CONTRIBUTING.md mgmt* script/ vendor/ kvlogger.go .dockerignore .gitignore README.md * Remove config, add JWT support from github.com/mgit-at/lfs-test-server Imported commit f0cdcc5a01599c5a955dc1bbf683bb4acecdba83 * Add LFS settings * Add LFS meta object model * Add LFS routes and initialization * Import github.com/dgrijalva/jwt-go into vendor/ * Adapt LFS module: handlers, routing, meta store * Move LFS routes to /user/repo/info/lfs/* * Add request header checks to LFS BatchHandler / PostHandler * Implement LFS basic authentication * Rework JWT secret generation / load * Implement LFS SSH token authentication with JWT Specification: https://github.com/github/git-lfs/tree/master/docs/api * Integrate LFS settings into install process * Remove LFS objects when repository is deleted Only removes objects from content store when deleted repo is the only referencing repository * Make LFS module stateless Fixes bug where LFS would not work after installation without restarting Gitea * Change 500 'Internal Server Error' to 400 'Bad Request' * Change sql query to xorm call * Remove unneeded type from LFS module * Change internal imports to code.gitea.io/gitea/ * Add Gitea authors copyright * Change basic auth realm to "gitea-lfs" * Add unique indexes to LFS model * Use xorm count function in LFS check on repository delete * Return io.ReadCloser from content store and close after usage * Add LFS info to runWeb() * Export LFS content store base path * LFS file download from UI * Work around git-lfs client issue with unauthenticated requests Returning a dummy Authorization header for unauthenticated requests lets git-lfs client skip asking for auth credentials See: https://github.com/github/git-lfs/issues/1088 * Fix unauthenticated UI downloads from public repositories * Authentication check order, Finish LFS file view logic * Ignore LFS hooks if installed for current OS user Fixes Gitea UI actions for repositories tracking LFS files. Checks for minimum needed git version by parsing the semantic version string. * Hide LFS metafile diff from commit view, marking as binary * Show LFS notice if file in commit view is tracked * Add notbefore/nbf JWT claim * Correct lint suggestions - comments for structs and functions - Add comments to LFS model - Function comment for GetRandomBytesAsBase64 - LFS server function comments and lint variable suggestion * Move secret generation code out of conditional Ensures no LFS code may run with an empty secret * Do not hand out JWT tokens if LFS server support is disabled
7 лет назад
8 лет назад
Add context cache as a request level cache (#22294) To avoid duplicated load of the same data in an HTTP request, we can set a context cache to do that. i.e. Some pages may load a user from a database with the same id in different areas on the same page. But the code is hidden in two different deep logic. How should we share the user? As a result of this PR, now if both entry functions accept `context.Context` as the first parameter and we just need to refactor `GetUserByID` to reuse the user from the context cache. Then it will not be loaded twice on an HTTP request. But of course, sometimes we would like to reload an object from the database, that's why `RemoveContextData` is also exposed. The core context cache is here. It defines a new context ```go type cacheContext struct { ctx context.Context data map[any]map[any]any lock sync.RWMutex } var cacheContextKey = struct{}{} func WithCacheContext(ctx context.Context) context.Context { return context.WithValue(ctx, cacheContextKey, &cacheContext{ ctx: ctx, data: make(map[any]map[any]any), }) } ``` Then you can use the below 4 methods to read/write/del the data within the same context. ```go func GetContextData(ctx context.Context, tp, key any) any func SetContextData(ctx context.Context, tp, key, value any) func RemoveContextData(ctx context.Context, tp, key any) func GetWithContextCache[T any](ctx context.Context, cacheGroupKey string, cacheTargetID any, f func() (T, error)) (T, error) ``` Then let's take a look at how `system.GetString` implement it. ```go func GetSetting(ctx context.Context, key string) (string, error) { return cache.GetWithContextCache(ctx, contextCacheKey, key, func() (string, error) { return cache.GetString(genSettingCacheKey(key), func() (string, error) { res, err := GetSettingNoCache(ctx, key) if err != nil { return "", err } return res.SettingValue, nil }) }) } ``` First, it will check if context data include the setting object with the key. If not, it will query from the global cache which may be memory or a Redis cache. If not, it will get the object from the database. In the end, if the object gets from the global cache or database, it will be set into the context cache. An object stored in the context cache will only be destroyed after the context disappeared.
1 год назад
Add context cache as a request level cache (#22294) To avoid duplicated load of the same data in an HTTP request, we can set a context cache to do that. i.e. Some pages may load a user from a database with the same id in different areas on the same page. But the code is hidden in two different deep logic. How should we share the user? As a result of this PR, now if both entry functions accept `context.Context` as the first parameter and we just need to refactor `GetUserByID` to reuse the user from the context cache. Then it will not be loaded twice on an HTTP request. But of course, sometimes we would like to reload an object from the database, that's why `RemoveContextData` is also exposed. The core context cache is here. It defines a new context ```go type cacheContext struct { ctx context.Context data map[any]map[any]any lock sync.RWMutex } var cacheContextKey = struct{}{} func WithCacheContext(ctx context.Context) context.Context { return context.WithValue(ctx, cacheContextKey, &cacheContext{ ctx: ctx, data: make(map[any]map[any]any), }) } ``` Then you can use the below 4 methods to read/write/del the data within the same context. ```go func GetContextData(ctx context.Context, tp, key any) any func SetContextData(ctx context.Context, tp, key, value any) func RemoveContextData(ctx context.Context, tp, key any) func GetWithContextCache[T any](ctx context.Context, cacheGroupKey string, cacheTargetID any, f func() (T, error)) (T, error) ``` Then let's take a look at how `system.GetString` implement it. ```go func GetSetting(ctx context.Context, key string) (string, error) { return cache.GetWithContextCache(ctx, contextCacheKey, key, func() (string, error) { return cache.GetString(genSettingCacheKey(key), func() (string, error) { res, err := GetSettingNoCache(ctx, key) if err != nil { return "", err } return res.SettingValue, nil }) }) } ``` First, it will check if context data include the setting object with the key. If not, it will query from the global cache which may be memory or a Redis cache. If not, it will get the object from the database. In the end, if the object gets from the global cache or database, it will be set into the context cache. An object stored in the context cache will only be destroyed after the context disappeared.
1 год назад
9 лет назад
9 лет назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
Refactor path & config system (#25330) # The problem There were many "path tricks": * By default, Gitea uses its program directory as its work path * Gitea tries to use the "work path" to guess its "custom path" and "custom conf (app.ini)" * Users might want to use other directories as work path * The non-default work path should be passed to Gitea by GITEA_WORK_DIR or "--work-path" * But some Gitea processes are started without these values * The "serv" process started by OpenSSH server * The CLI sub-commands started by site admin * The paths are guessed by SetCustomPathAndConf again and again * The default values of "work path / custom path / custom conf" can be changed when compiling # The solution * Use `InitWorkPathAndCommonConfig` to handle these path tricks, and use test code to cover its behaviors. * When Gitea's web server runs, write the WORK_PATH to "app.ini", this value must be the most correct one, because if this value is not right, users would find that the web UI doesn't work and then they should be able to fix it. * Then all other sub-commands can use the WORK_PATH in app.ini to initialize their paths. * By the way, when Gitea starts for git protocol, it shouldn't output any log, otherwise the git protocol gets broken and client blocks forever. The "work path" priority is: WORK_PATH in app.ini > cmd arg --work-path > env var GITEA_WORK_DIR > builtin default The "app.ini" searching order is: cmd arg --config > cmd arg "work path / custom path" > env var "work path / custom path" > builtin default ## ⚠️ BREAKING If your instance's "work path / custom path / custom conf" doesn't meet the requirements (eg: work path must be absolute), Gitea will report a fatal error and exit. You need to set these values according to the error log. ---- Close #24818 Close #24222 Close #21606 Close #21498 Close #25107 Close #24981 Maybe close #24503 Replace #23301 Replace #22754 And maybe more
11 месяцев назад
8 лет назад
8 лет назад
8 лет назад
10 лет назад
10 лет назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
10 лет назад
Fix various bugs for "install" page (#23194) ## TLDR * Fix the broken page / broken image problem when click "Install" * Close #20089 * Fix the Password Hash Algorithm display problem for #22942 * Close #23183 * Close #23184 ## Details ### The broken page / broken image problem when click "Install" (Redirect failed after install gitea #23184) Before: when click "install", all new requests will fail, because the server has been restarted. Users just see a broken page with broken images, sometimes the server is not ready but the user would have been redirect to "/user/login" page, then the users see a new broken page (connection refused or something wrong ...) After: only check InstallLock=true for necessary handlers, and sleep for a while before restarting the server, then the browser has enough time to load the "post-install" page. And there is a script to check whether "/user/login" is ready, the user will only be redirected to the login page when the server is ready. ### During new instance setup make 'Gitea Base URL' filled from window.location.origin #20089 If the "app_url" input contains `localhost` (the default value from config), use current window's location href as the `app_url` (aka ROOT_URL) ### Fix the Password Hash Algorithm display problem for "Provide the ability to set password hash algorithm parameters #22942" Before: the UI shows `pbkdf2$50000$50` <details> ![image](https://user-images.githubusercontent.com/2114189/221917143-e1e54798-1698-4fee-a18d-00c48081fc39.png) </details> After: the UI shows `pbkdf2` <details> ![image](https://user-images.githubusercontent.com/2114189/221916999-97a15be8-2ebb-4a01-bf93-dac18e354fcc.png) </details> ### GET data: net::ERR_INVALID_URL #23183 Cause by empty `data:` in `<link rel="manifest" href="data:{{.ManifestData}}">` --------- Co-authored-by: Jason Song <i@wolfogre.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
1 год назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2021 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. package install
  5. import (
  6. "fmt"
  7. "net/http"
  8. "os"
  9. "os/exec"
  10. "path/filepath"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "code.gitea.io/gitea/models/db"
  15. db_install "code.gitea.io/gitea/models/db/install"
  16. "code.gitea.io/gitea/models/migrations"
  17. system_model "code.gitea.io/gitea/models/system"
  18. user_model "code.gitea.io/gitea/models/user"
  19. "code.gitea.io/gitea/modules/auth/password/hash"
  20. "code.gitea.io/gitea/modules/base"
  21. "code.gitea.io/gitea/modules/context"
  22. "code.gitea.io/gitea/modules/generate"
  23. "code.gitea.io/gitea/modules/graceful"
  24. "code.gitea.io/gitea/modules/log"
  25. "code.gitea.io/gitea/modules/setting"
  26. "code.gitea.io/gitea/modules/templates"
  27. "code.gitea.io/gitea/modules/translation"
  28. "code.gitea.io/gitea/modules/user"
  29. "code.gitea.io/gitea/modules/util"
  30. "code.gitea.io/gitea/modules/web"
  31. "code.gitea.io/gitea/modules/web/middleware"
  32. "code.gitea.io/gitea/routers/common"
  33. "code.gitea.io/gitea/services/forms"
  34. "gitea.com/go-chi/session"
  35. )
  36. const (
  37. // tplInstall template for installation page
  38. tplInstall base.TplName = "install"
  39. tplPostInstall base.TplName = "post-install"
  40. )
  41. // getSupportedDbTypeNames returns a slice for supported database types and names. The slice is used to keep the order
  42. func getSupportedDbTypeNames() (dbTypeNames []map[string]string) {
  43. for _, t := range setting.SupportedDatabaseTypes {
  44. dbTypeNames = append(dbTypeNames, map[string]string{"type": t, "name": setting.DatabaseTypeNames[t]})
  45. }
  46. return dbTypeNames
  47. }
  48. // Contexter prepare for rendering installation page
  49. func Contexter() func(next http.Handler) http.Handler {
  50. rnd := templates.HTMLRenderer()
  51. dbTypeNames := getSupportedDbTypeNames()
  52. envConfigKeys := setting.CollectEnvConfigKeys()
  53. return func(next http.Handler) http.Handler {
  54. return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
  55. base, baseCleanUp := context.NewBaseContext(resp, req)
  56. defer baseCleanUp()
  57. ctx := context.NewWebContext(base, rnd, session.GetSession(req))
  58. ctx.AppendContextValue(context.WebContextKey, ctx)
  59. ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
  60. ctx.Data.MergeFrom(middleware.ContextData{
  61. "Context": ctx, // TODO: use "ctx" in template and remove this
  62. "locale": ctx.Locale,
  63. "Title": ctx.Locale.Tr("install.install"),
  64. "PageIsInstall": true,
  65. "DbTypeNames": dbTypeNames,
  66. "EnvConfigKeys": envConfigKeys,
  67. "CustomConfFile": setting.CustomConf,
  68. "AllLangs": translation.AllLangs(),
  69. "PasswordHashAlgorithms": hash.RecommendedHashAlgorithms,
  70. })
  71. next.ServeHTTP(resp, ctx.Req)
  72. })
  73. }
  74. }
  75. // Install render installation page
  76. func Install(ctx *context.Context) {
  77. if setting.InstallLock {
  78. InstallDone(ctx)
  79. return
  80. }
  81. form := forms.InstallForm{}
  82. // Database settings
  83. form.DbHost = setting.Database.Host
  84. form.DbUser = setting.Database.User
  85. form.DbPasswd = setting.Database.Passwd
  86. form.DbName = setting.Database.Name
  87. form.DbPath = setting.Database.Path
  88. form.DbSchema = setting.Database.Schema
  89. form.SSLMode = setting.Database.SSLMode
  90. curDBType := setting.Database.Type.String()
  91. var isCurDBTypeSupported bool
  92. for _, dbType := range setting.SupportedDatabaseTypes {
  93. if dbType == curDBType {
  94. isCurDBTypeSupported = true
  95. break
  96. }
  97. }
  98. if !isCurDBTypeSupported {
  99. curDBType = "mysql"
  100. }
  101. ctx.Data["CurDbType"] = curDBType
  102. // Application general settings
  103. form.AppName = setting.AppName
  104. form.RepoRootPath = setting.RepoRootPath
  105. form.LFSRootPath = setting.LFS.Storage.Path
  106. // Note(unknown): it's hard for Windows users change a running user,
  107. // so just use current one if config says default.
  108. if setting.IsWindows && setting.RunUser == "git" {
  109. form.RunUser = user.CurrentUsername()
  110. } else {
  111. form.RunUser = setting.RunUser
  112. }
  113. form.Domain = setting.Domain
  114. form.SSHPort = setting.SSH.Port
  115. form.HTTPPort = setting.HTTPPort
  116. form.AppURL = setting.AppURL
  117. form.LogRootPath = setting.Log.RootPath
  118. // E-mail service settings
  119. if setting.MailService != nil {
  120. form.SMTPAddr = setting.MailService.SMTPAddr
  121. form.SMTPPort = setting.MailService.SMTPPort
  122. form.SMTPFrom = setting.MailService.From
  123. form.SMTPUser = setting.MailService.User
  124. form.SMTPPasswd = setting.MailService.Passwd
  125. }
  126. form.RegisterConfirm = setting.Service.RegisterEmailConfirm
  127. form.MailNotify = setting.Service.EnableNotifyMail
  128. // Server and other services settings
  129. form.OfflineMode = setting.OfflineMode
  130. form.DisableGravatar = setting.DisableGravatar // when installing, there is no database connection so that given a default value
  131. form.EnableFederatedAvatar = setting.EnableFederatedAvatar // when installing, there is no database connection so that given a default value
  132. form.EnableOpenIDSignIn = setting.Service.EnableOpenIDSignIn
  133. form.EnableOpenIDSignUp = setting.Service.EnableOpenIDSignUp
  134. form.DisableRegistration = setting.Service.DisableRegistration
  135. form.AllowOnlyExternalRegistration = setting.Service.AllowOnlyExternalRegistration
  136. form.EnableCaptcha = setting.Service.EnableCaptcha
  137. form.RequireSignInView = setting.Service.RequireSignInView
  138. form.DefaultKeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
  139. form.DefaultAllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
  140. form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking
  141. form.NoReplyAddress = setting.Service.NoReplyAddress
  142. form.PasswordAlgorithm = hash.ConfigHashAlgorithm(setting.PasswordHashAlgo)
  143. middleware.AssignForm(form, ctx.Data)
  144. ctx.HTML(http.StatusOK, tplInstall)
  145. }
  146. func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool {
  147. var err error
  148. if (setting.Database.Type == "sqlite3") &&
  149. len(setting.Database.Path) == 0 {
  150. ctx.Data["Err_DbPath"] = true
  151. ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), tplInstall, form)
  152. return false
  153. }
  154. // Check if the user is trying to re-install in an installed database
  155. db.UnsetDefaultEngine()
  156. defer db.UnsetDefaultEngine()
  157. if err = db.InitEngine(ctx); err != nil {
  158. if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
  159. ctx.Data["Err_DbType"] = true
  160. ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://docs.gitea.com/installation/install-from-binary"), tplInstall, form)
  161. } else {
  162. ctx.Data["Err_DbSetting"] = true
  163. ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), tplInstall, form)
  164. }
  165. return false
  166. }
  167. err = db_install.CheckDatabaseConnection()
  168. if err != nil {
  169. ctx.Data["Err_DbSetting"] = true
  170. ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), tplInstall, form)
  171. return false
  172. }
  173. hasPostInstallationUser, err := db_install.HasPostInstallationUsers()
  174. if err != nil {
  175. ctx.Data["Err_DbSetting"] = true
  176. ctx.RenderWithErr(ctx.Tr("install.invalid_db_table", "user", err), tplInstall, form)
  177. return false
  178. }
  179. dbMigrationVersion, err := db_install.GetMigrationVersion()
  180. if err != nil {
  181. ctx.Data["Err_DbSetting"] = true
  182. ctx.RenderWithErr(ctx.Tr("install.invalid_db_table", "version", err), tplInstall, form)
  183. return false
  184. }
  185. if hasPostInstallationUser && dbMigrationVersion > 0 {
  186. log.Error("The database is likely to have been used by Gitea before, database migration version=%d", dbMigrationVersion)
  187. confirmed := form.ReinstallConfirmFirst && form.ReinstallConfirmSecond && form.ReinstallConfirmThird
  188. if !confirmed {
  189. ctx.Data["Err_DbInstalledBefore"] = true
  190. ctx.RenderWithErr(ctx.Tr("install.reinstall_error"), tplInstall, form)
  191. return false
  192. }
  193. log.Info("User confirmed re-installation of Gitea into a pre-existing database")
  194. }
  195. if hasPostInstallationUser || dbMigrationVersion > 0 {
  196. log.Info("Gitea will be installed in a database with: hasPostInstallationUser=%v, dbMigrationVersion=%v", hasPostInstallationUser, dbMigrationVersion)
  197. }
  198. return true
  199. }
  200. // SubmitInstall response for submit install items
  201. func SubmitInstall(ctx *context.Context) {
  202. if setting.InstallLock {
  203. InstallDone(ctx)
  204. return
  205. }
  206. var err error
  207. form := *web.GetForm(ctx).(*forms.InstallForm)
  208. // fix form values
  209. if form.AppURL != "" && form.AppURL[len(form.AppURL)-1] != '/' {
  210. form.AppURL += "/"
  211. }
  212. ctx.Data["CurDbType"] = form.DbType
  213. if ctx.HasError() {
  214. ctx.Data["Err_SMTP"] = ctx.Data["Err_SMTPUser"] != nil
  215. ctx.Data["Err_Admin"] = ctx.Data["Err_AdminName"] != nil || ctx.Data["Err_AdminPasswd"] != nil || ctx.Data["Err_AdminEmail"] != nil
  216. ctx.HTML(http.StatusOK, tplInstall)
  217. return
  218. }
  219. if _, err = exec.LookPath("git"); err != nil {
  220. ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), tplInstall, &form)
  221. return
  222. }
  223. // ---- Basic checks are passed, now test configuration.
  224. // Test database setting.
  225. setting.Database.Type = setting.DatabaseType(form.DbType)
  226. setting.Database.Host = form.DbHost
  227. setting.Database.User = form.DbUser
  228. setting.Database.Passwd = form.DbPasswd
  229. setting.Database.Name = form.DbName
  230. setting.Database.Schema = form.DbSchema
  231. setting.Database.SSLMode = form.SSLMode
  232. setting.Database.Path = form.DbPath
  233. setting.Database.LogSQL = !setting.IsProd
  234. if !checkDatabase(ctx, &form) {
  235. return
  236. }
  237. // Prepare AppDataPath, it is very important for Gitea
  238. if err = setting.PrepareAppDataPath(); err != nil {
  239. ctx.RenderWithErr(ctx.Tr("install.invalid_app_data_path", err), tplInstall, &form)
  240. return
  241. }
  242. // Test repository root path.
  243. form.RepoRootPath = strings.ReplaceAll(form.RepoRootPath, "\\", "/")
  244. if err = os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
  245. ctx.Data["Err_RepoRootPath"] = true
  246. ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), tplInstall, &form)
  247. return
  248. }
  249. // Test LFS root path if not empty, empty meaning disable LFS
  250. if form.LFSRootPath != "" {
  251. form.LFSRootPath = strings.ReplaceAll(form.LFSRootPath, "\\", "/")
  252. if err := os.MkdirAll(form.LFSRootPath, os.ModePerm); err != nil {
  253. ctx.Data["Err_LFSRootPath"] = true
  254. ctx.RenderWithErr(ctx.Tr("install.invalid_lfs_path", err), tplInstall, &form)
  255. return
  256. }
  257. }
  258. // Test log root path.
  259. form.LogRootPath = strings.ReplaceAll(form.LogRootPath, "\\", "/")
  260. if err = os.MkdirAll(form.LogRootPath, os.ModePerm); err != nil {
  261. ctx.Data["Err_LogRootPath"] = true
  262. ctx.RenderWithErr(ctx.Tr("install.invalid_log_root_path", err), tplInstall, &form)
  263. return
  264. }
  265. currentUser, match := setting.IsRunUserMatchCurrentUser(form.RunUser)
  266. if !match {
  267. ctx.Data["Err_RunUser"] = true
  268. ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", form.RunUser, currentUser), tplInstall, &form)
  269. return
  270. }
  271. // Check logic loophole between disable self-registration and no admin account.
  272. if form.DisableRegistration && len(form.AdminName) == 0 {
  273. ctx.Data["Err_Services"] = true
  274. ctx.Data["Err_Admin"] = true
  275. ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), tplInstall, form)
  276. return
  277. }
  278. // Check admin user creation
  279. if len(form.AdminName) > 0 {
  280. // Ensure AdminName is valid
  281. if err := user_model.IsUsableUsername(form.AdminName); err != nil {
  282. ctx.Data["Err_Admin"] = true
  283. ctx.Data["Err_AdminName"] = true
  284. if db.IsErrNameReserved(err) {
  285. ctx.RenderWithErr(ctx.Tr("install.err_admin_name_is_reserved"), tplInstall, form)
  286. return
  287. } else if db.IsErrNamePatternNotAllowed(err) {
  288. ctx.RenderWithErr(ctx.Tr("install.err_admin_name_pattern_not_allowed"), tplInstall, form)
  289. return
  290. }
  291. ctx.RenderWithErr(ctx.Tr("install.err_admin_name_is_invalid"), tplInstall, form)
  292. return
  293. }
  294. // Check Admin email
  295. if len(form.AdminEmail) == 0 {
  296. ctx.Data["Err_Admin"] = true
  297. ctx.Data["Err_AdminEmail"] = true
  298. ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_email"), tplInstall, form)
  299. return
  300. }
  301. // Check admin password.
  302. if len(form.AdminPasswd) == 0 {
  303. ctx.Data["Err_Admin"] = true
  304. ctx.Data["Err_AdminPasswd"] = true
  305. ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), tplInstall, form)
  306. return
  307. }
  308. if form.AdminPasswd != form.AdminConfirmPasswd {
  309. ctx.Data["Err_Admin"] = true
  310. ctx.Data["Err_AdminPasswd"] = true
  311. ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplInstall, form)
  312. return
  313. }
  314. }
  315. // Init the engine with migration
  316. if err = db.InitEngineWithMigration(ctx, migrations.Migrate); err != nil {
  317. db.UnsetDefaultEngine()
  318. ctx.Data["Err_DbSetting"] = true
  319. ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), tplInstall, &form)
  320. return
  321. }
  322. // Save settings.
  323. cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
  324. if err != nil {
  325. log.Error("Failed to load custom conf '%s': %v", setting.CustomConf, err)
  326. }
  327. cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
  328. cfg.Section("").Key("RUN_USER").SetValue(form.RunUser)
  329. cfg.Section("").Key("WORK_PATH").SetValue(setting.AppWorkPath)
  330. cfg.Section("").Key("RUN_MODE").SetValue("prod")
  331. cfg.Section("database").Key("DB_TYPE").SetValue(setting.Database.Type.String())
  332. cfg.Section("database").Key("HOST").SetValue(setting.Database.Host)
  333. cfg.Section("database").Key("NAME").SetValue(setting.Database.Name)
  334. cfg.Section("database").Key("USER").SetValue(setting.Database.User)
  335. cfg.Section("database").Key("PASSWD").SetValue(setting.Database.Passwd)
  336. cfg.Section("database").Key("SCHEMA").SetValue(setting.Database.Schema)
  337. cfg.Section("database").Key("SSL_MODE").SetValue(setting.Database.SSLMode)
  338. cfg.Section("database").Key("PATH").SetValue(setting.Database.Path)
  339. cfg.Section("database").Key("LOG_SQL").SetValue("false") // LOG_SQL is rarely helpful
  340. cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
  341. cfg.Section("server").Key("SSH_DOMAIN").SetValue(form.Domain)
  342. cfg.Section("server").Key("DOMAIN").SetValue(form.Domain)
  343. cfg.Section("server").Key("HTTP_PORT").SetValue(form.HTTPPort)
  344. cfg.Section("server").Key("ROOT_URL").SetValue(form.AppURL)
  345. cfg.Section("server").Key("APP_DATA_PATH").SetValue(setting.AppDataPath)
  346. if form.SSHPort == 0 {
  347. cfg.Section("server").Key("DISABLE_SSH").SetValue("true")
  348. } else {
  349. cfg.Section("server").Key("DISABLE_SSH").SetValue("false")
  350. cfg.Section("server").Key("SSH_PORT").SetValue(fmt.Sprint(form.SSHPort))
  351. }
  352. if form.LFSRootPath != "" {
  353. cfg.Section("server").Key("LFS_START_SERVER").SetValue("true")
  354. cfg.Section("lfs").Key("PATH").SetValue(form.LFSRootPath)
  355. var lfsJwtSecret string
  356. if _, lfsJwtSecret, err = generate.NewJwtSecretBase64(); err != nil {
  357. ctx.RenderWithErr(ctx.Tr("install.lfs_jwt_secret_failed", err), tplInstall, &form)
  358. return
  359. }
  360. cfg.Section("server").Key("LFS_JWT_SECRET").SetValue(lfsJwtSecret)
  361. } else {
  362. cfg.Section("server").Key("LFS_START_SERVER").SetValue("false")
  363. }
  364. if len(strings.TrimSpace(form.SMTPAddr)) > 0 {
  365. cfg.Section("mailer").Key("ENABLED").SetValue("true")
  366. cfg.Section("mailer").Key("SMTP_ADDR").SetValue(form.SMTPAddr)
  367. cfg.Section("mailer").Key("SMTP_PORT").SetValue(form.SMTPPort)
  368. cfg.Section("mailer").Key("FROM").SetValue(form.SMTPFrom)
  369. cfg.Section("mailer").Key("USER").SetValue(form.SMTPUser)
  370. cfg.Section("mailer").Key("PASSWD").SetValue(form.SMTPPasswd)
  371. } else {
  372. cfg.Section("mailer").Key("ENABLED").SetValue("false")
  373. }
  374. cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(fmt.Sprint(form.RegisterConfirm))
  375. cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(fmt.Sprint(form.MailNotify))
  376. cfg.Section("server").Key("OFFLINE_MODE").SetValue(fmt.Sprint(form.OfflineMode))
  377. // if you are reinstalling, this maybe not right because of missing version
  378. if err := system_model.SetSettingNoVersion(ctx, system_model.KeyPictureDisableGravatar, strconv.FormatBool(form.DisableGravatar)); err != nil {
  379. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  380. return
  381. }
  382. if err := system_model.SetSettingNoVersion(ctx, system_model.KeyPictureEnableFederatedAvatar, strconv.FormatBool(form.EnableFederatedAvatar)); err != nil {
  383. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  384. return
  385. }
  386. cfg.Section("openid").Key("ENABLE_OPENID_SIGNIN").SetValue(fmt.Sprint(form.EnableOpenIDSignIn))
  387. cfg.Section("openid").Key("ENABLE_OPENID_SIGNUP").SetValue(fmt.Sprint(form.EnableOpenIDSignUp))
  388. cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(fmt.Sprint(form.DisableRegistration))
  389. cfg.Section("service").Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").SetValue(fmt.Sprint(form.AllowOnlyExternalRegistration))
  390. cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(fmt.Sprint(form.EnableCaptcha))
  391. cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(fmt.Sprint(form.RequireSignInView))
  392. cfg.Section("service").Key("DEFAULT_KEEP_EMAIL_PRIVATE").SetValue(fmt.Sprint(form.DefaultKeepEmailPrivate))
  393. cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").SetValue(fmt.Sprint(form.DefaultAllowCreateOrganization))
  394. cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(fmt.Sprint(form.DefaultEnableTimetracking))
  395. cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(fmt.Sprint(form.NoReplyAddress))
  396. cfg.Section("cron.update_checker").Key("ENABLED").SetValue(fmt.Sprint(form.EnableUpdateChecker))
  397. cfg.Section("session").Key("PROVIDER").SetValue("file")
  398. cfg.Section("log").Key("MODE").MustString("console")
  399. cfg.Section("log").Key("LEVEL").SetValue(setting.Log.Level.String())
  400. cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath)
  401. cfg.Section("repository.pull-request").Key("DEFAULT_MERGE_STYLE").SetValue("merge")
  402. cfg.Section("repository.signing").Key("DEFAULT_TRUST_MODEL").SetValue("committer")
  403. cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
  404. // the internal token could be read from INTERNAL_TOKEN or INTERNAL_TOKEN_URI (the file is guaranteed to be non-empty)
  405. // if there is no InternalToken, generate one and save to security.INTERNAL_TOKEN
  406. if setting.InternalToken == "" {
  407. var internalToken string
  408. if internalToken, err = generate.NewInternalToken(); err != nil {
  409. ctx.RenderWithErr(ctx.Tr("install.internal_token_failed", err), tplInstall, &form)
  410. return
  411. }
  412. cfg.Section("security").Key("INTERNAL_TOKEN").SetValue(internalToken)
  413. }
  414. // if there is already a SECRET_KEY, we should not overwrite it, otherwise the encrypted data will not be able to be decrypted
  415. if setting.SecretKey == "" {
  416. var secretKey string
  417. if secretKey, err = generate.NewSecretKey(); err != nil {
  418. ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), tplInstall, &form)
  419. return
  420. }
  421. cfg.Section("security").Key("SECRET_KEY").SetValue(secretKey)
  422. }
  423. if len(form.PasswordAlgorithm) > 0 {
  424. var algorithm *hash.PasswordHashAlgorithm
  425. setting.PasswordHashAlgo, algorithm = hash.SetDefaultPasswordHashAlgorithm(form.PasswordAlgorithm)
  426. if algorithm == nil {
  427. ctx.RenderWithErr(ctx.Tr("install.invalid_password_algorithm"), tplInstall, &form)
  428. return
  429. }
  430. cfg.Section("security").Key("PASSWORD_HASH_ALGO").SetValue(form.PasswordAlgorithm)
  431. }
  432. log.Info("Save settings to custom config file %s", setting.CustomConf)
  433. err = os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
  434. if err != nil {
  435. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  436. return
  437. }
  438. setting.EnvironmentToConfig(cfg, os.Environ())
  439. if err = cfg.SaveTo(setting.CustomConf); err != nil {
  440. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  441. return
  442. }
  443. // unset default engine before reload database setting
  444. db.UnsetDefaultEngine()
  445. // ---- All checks are passed
  446. // Reload settings (and re-initialize database connection)
  447. setting.InitCfgProvider(setting.CustomConf)
  448. setting.LoadCommonSettings()
  449. setting.MustInstalled()
  450. setting.LoadDBSetting()
  451. if err := common.InitDBEngine(ctx); err != nil {
  452. log.Fatal("ORM engine initialization failed: %v", err)
  453. }
  454. // Create admin account
  455. if len(form.AdminName) > 0 {
  456. u := &user_model.User{
  457. Name: form.AdminName,
  458. Email: form.AdminEmail,
  459. Passwd: form.AdminPasswd,
  460. IsAdmin: true,
  461. }
  462. overwriteDefault := &user_model.CreateUserOverwriteOptions{
  463. IsRestricted: util.OptionalBoolFalse,
  464. IsActive: util.OptionalBoolTrue,
  465. }
  466. if err = user_model.CreateUser(u, overwriteDefault); err != nil {
  467. if !user_model.IsErrUserAlreadyExist(err) {
  468. setting.InstallLock = false
  469. ctx.Data["Err_AdminName"] = true
  470. ctx.Data["Err_AdminEmail"] = true
  471. ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), tplInstall, &form)
  472. return
  473. }
  474. log.Info("Admin account already exist")
  475. u, _ = user_model.GetUserByName(ctx, u.Name)
  476. }
  477. days := 86400 * setting.LogInRememberDays
  478. ctx.SetSiteCookie(setting.CookieUserName, u.Name, days)
  479. ctx.SetSuperSecureCookie(base.EncodeMD5(u.Rands+u.Passwd),
  480. setting.CookieRememberName, u.Name, days)
  481. // Auto-login for admin
  482. if err = ctx.Session.Set("uid", u.ID); err != nil {
  483. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  484. return
  485. }
  486. if err = ctx.Session.Set("uname", u.Name); err != nil {
  487. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  488. return
  489. }
  490. if err = ctx.Session.Release(); err != nil {
  491. ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
  492. return
  493. }
  494. }
  495. setting.ClearEnvConfigKeys()
  496. log.Info("First-time run install finished!")
  497. InstallDone(ctx)
  498. go func() {
  499. // Sleep for a while to make sure the user's browser has loaded the post-install page and its assets (images, css, js)
  500. // What if this duration is not long enough? That's impossible -- if the user can't load the simple page in time, how could they install or use Gitea in the future ....
  501. time.Sleep(3 * time.Second)
  502. // Now get the http.Server from this request and shut it down
  503. // NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
  504. srv := ctx.Value(http.ServerContextKey).(*http.Server)
  505. if err := srv.Shutdown(graceful.GetManager().HammerContext()); err != nil {
  506. log.Error("Unable to shutdown the install server! Error: %v", err)
  507. }
  508. // After the HTTP server for "install" shuts down, the `runWeb()` will continue to run the "normal" server
  509. }()
  510. }
  511. // InstallDone shows the "post-install" page, makes it easier to develop the page.
  512. // The name is not called as "PostInstall" to avoid misinterpretation as a handler for "POST /install"
  513. func InstallDone(ctx *context.Context) { //nolint
  514. ctx.HTML(http.StatusOK, tplPostInstall)
  515. }