mirror of
https://github.com/thomiceli/opengist.git
synced 2024-12-31 15:22:39 +00:00
Add require login feature to see gists
This commit is contained in:
parent
64d0818c9f
commit
333efeacbf
12 changed files with 77 additions and 23 deletions
|
@ -31,6 +31,7 @@ A self-hosted pastebin **powered by Git**. [Try it here](https://opengist.thomic
|
|||
* Avatars
|
||||
* Responsive UI
|
||||
* Enable or disable signups
|
||||
* Restrict or unrestrict snippets visibility to anonymous users
|
||||
* Admin panel : delete users/gists; clean database/filesystem by syncing gists
|
||||
* SQLite database
|
||||
* Logging
|
||||
|
|
|
@ -11,6 +11,7 @@ type AdminSetting struct {
|
|||
|
||||
const (
|
||||
SettingDisableSignup = "disable-signup"
|
||||
SettingRequireLogin = "require-login"
|
||||
)
|
||||
|
||||
func GetSetting(key string) (string, error) {
|
||||
|
@ -19,9 +20,24 @@ func GetSetting(key string) (string, error) {
|
|||
return setting.Value, err
|
||||
}
|
||||
|
||||
func GetSettings() (map[string]string, error) {
|
||||
var settings []AdminSetting
|
||||
err := db.Find(&settings).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[string]string)
|
||||
for _, setting := range settings {
|
||||
result[setting.Key] = setting.Value
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func UpdateSetting(key string, value string) error {
|
||||
return db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "key"}}, // key colume
|
||||
Columns: []clause.Column{{Name: "key"}}, // key column
|
||||
DoUpdates: clause.AssignmentColumns([]string{"value"}),
|
||||
}).Create(&AdminSetting{
|
||||
Key: key,
|
||||
|
|
|
@ -28,6 +28,7 @@ func Setup(dbpath string) error {
|
|||
// Default admin setting values
|
||||
return initAdminSettings(map[string]string{
|
||||
SettingDisableSignup: "0",
|
||||
SettingRequireLogin: "0",
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,12 @@ func runGitCommand(ch ssh.Channel, gitCmd string, keyID uint, ip string) error {
|
|||
return errors.New("gist not found")
|
||||
}
|
||||
|
||||
if verb == "receive-pack" {
|
||||
requireLogin, err := models.GetSetting(models.SettingRequireLogin)
|
||||
if err != nil {
|
||||
return errors.New("internal server error")
|
||||
}
|
||||
|
||||
if verb == "receive-pack" || requireLogin == "1" {
|
||||
user, err := models.GetUserBySSHKeyID(keyID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
|
|
@ -30,7 +30,7 @@ func register(ctx echo.Context) error {
|
|||
}
|
||||
|
||||
func processRegister(ctx echo.Context) error {
|
||||
if getData(ctx, "signupDisabled") == true {
|
||||
if getData(ctx, "DisableSignup") == true {
|
||||
return errorRes(403, "Signing up is disabled", nil)
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,10 @@ func oauthCallback(ctx echo.Context) error {
|
|||
// if user is not in database, create it
|
||||
userDB, err := models.GetUserByProvider(user.UserID, user.Provider)
|
||||
if err != nil {
|
||||
if getData(ctx, "DisableSignup") == true {
|
||||
return errorRes(403, "Signing up is disabled", nil)
|
||||
}
|
||||
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errorRes(500, "Cannot get user", err)
|
||||
}
|
||||
|
@ -166,10 +170,6 @@ func oauthCallback(ctx echo.Context) error {
|
|||
}
|
||||
|
||||
if err = userDB.Create(); err != nil {
|
||||
if getData(ctx, "signupDisabled") == true {
|
||||
return errorRes(403, "Signing up is disabled", nil)
|
||||
}
|
||||
|
||||
if models.IsUniqueConstraintViolation(err) {
|
||||
addFlash(ctx, "Username "+user.NickName+" already exists in Opengist", "error")
|
||||
return redirect(ctx, "/login")
|
||||
|
@ -281,7 +281,7 @@ func oauth(ctx echo.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
ctxValue := context.WithValue(ctx.Request().Context(), providerKey, provider)
|
||||
ctxValue := context.WithValue(ctx.Request().Context(), gothic.ProviderParamKey, provider)
|
||||
ctx.SetRequest(ctx.Request().WithContext(ctxValue))
|
||||
if provider != "github" && provider != "gitea" {
|
||||
return errorRes(400, "Unsupported provider", nil)
|
||||
|
|
|
@ -47,9 +47,10 @@ func gitHttp(ctx echo.Context) error {
|
|||
|
||||
gist := getData(ctx, "gist").(*models.Gist)
|
||||
|
||||
noAuth := ctx.QueryParam("service") == "git-upload-pack" ||
|
||||
noAuth := (ctx.QueryParam("service") == "git-upload-pack" ||
|
||||
strings.HasSuffix(ctx.Request().URL.Path, "git-upload-pack") ||
|
||||
ctx.Request().Method == "GET"
|
||||
ctx.Request().Method == "GET") &&
|
||||
!getData(ctx, "RequireLogin").(bool)
|
||||
|
||||
repositoryPath := git.RepositoryPath(gist.User.Username, gist.Uuid)
|
||||
|
||||
|
|
|
@ -191,12 +191,12 @@ func Start() {
|
|||
g2.PUT("/set-setting", adminSetSetting)
|
||||
}
|
||||
|
||||
g1.GET("/all", allGists)
|
||||
g1.GET("/:user", allGists)
|
||||
g1.GET("/all", allGists, checkRequireLogin)
|
||||
g1.GET("/:user", allGists, checkRequireLogin)
|
||||
|
||||
g3 := g1.Group("/:user/:gistname")
|
||||
{
|
||||
g3.Use(gistInit)
|
||||
g3.Use(checkRequireLogin, gistInit)
|
||||
g3.GET("", gistIndex)
|
||||
g3.GET("/rev/:revision", gistIndex)
|
||||
g3.GET("/revisions", revisions)
|
||||
|
@ -243,11 +243,9 @@ func dataInit(next echo.HandlerFunc) echo.HandlerFunc {
|
|||
ctx.SetRequest(ctx.Request().WithContext(ctxValue))
|
||||
setData(ctx, "loadStartTime", time.Now())
|
||||
|
||||
disableSignup, err := models.GetSetting(models.SettingDisableSignup)
|
||||
if err != nil {
|
||||
return errorRes(500, "Cannot read setting from database", err)
|
||||
if err := loadSettings(ctx); err != nil {
|
||||
return errorRes(500, "Cannot read settings from database", err)
|
||||
}
|
||||
setData(ctx, "signupDisabled", disableSignup == "1")
|
||||
|
||||
setData(ctx, "githubOauth", config.C.GithubClientKey != "" && config.C.GithubSecret != "")
|
||||
setData(ctx, "giteaOauth", config.C.GiteaClientKey != "" && config.C.GiteaSecret != "")
|
||||
|
@ -318,6 +316,21 @@ func logged(next echo.HandlerFunc) echo.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func checkRequireLogin(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(ctx echo.Context) error {
|
||||
if user := getUserLogged(ctx); user != nil {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
require := getData(ctx, "RequireLogin")
|
||||
if require == true {
|
||||
addFlash(ctx, "You must be logged in to access gists", "error")
|
||||
return redirect(ctx, "/login")
|
||||
}
|
||||
return next(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func cacheControl(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
c.Response().Header().Set(echo.HeaderCacheControl, "public, max-age=31536000")
|
||||
|
|
|
@ -18,10 +18,8 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type providerKeyType string
|
||||
type dataTypeKey string
|
||||
|
||||
const providerKey providerKeyType = "provider"
|
||||
const dataKey dataTypeKey = "data"
|
||||
|
||||
func setData(ctx echo.Context, key string, value any) {
|
||||
|
@ -110,6 +108,20 @@ func deleteCsrfCookie(ctx echo.Context) {
|
|||
ctx.SetCookie(&http.Cookie{Name: "_csrf", Path: "/", MaxAge: -1})
|
||||
}
|
||||
|
||||
func loadSettings(ctx echo.Context) error {
|
||||
settings, err := models.GetSettings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, value := range settings {
|
||||
s := strings.ReplaceAll(key, "-", " ")
|
||||
s = title.String(s)
|
||||
setData(ctx, strings.ReplaceAll(s, " ", ""), value == "1")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type OpengistValidator struct {
|
||||
v *validator.Validate
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
document.addEventListener('DOMContentLoaded', () => {
|
||||
registerDomSetting(document.getElementById('disable-signup') as HTMLInputElement);
|
||||
registerDomSetting(document.getElementById('require-login') as HTMLInputElement);
|
||||
});
|
||||
|
||||
const setSetting = (key: string, value: string) => {
|
||||
|
|
2
templates/base/base_header.html
vendored
2
templates/base/base_header.html
vendored
|
@ -66,7 +66,7 @@
|
|||
</svg>
|
||||
</a>
|
||||
{{ else }}
|
||||
{{ if not .signupDisabled }}
|
||||
{{ if not .DisableSignup }}
|
||||
<a href="/register" class="inline-flex text-slate-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">
|
||||
<p class="text-slate-300 mr-1">Register</p>
|
||||
</a>
|
||||
|
|
6
templates/pages/admin_index.html
vendored
6
templates/pages/admin_index.html
vendored
|
@ -81,7 +81,11 @@
|
|||
<div class="space-y-2">
|
||||
<div>
|
||||
<label for="disable-signup" class="text-sm text-slate-300">Disable signup</label>
|
||||
<input type="checkbox" id="disable-signup" name="disable-signup" {{ if .signupDisabled }}checked="checked"{{ end }} class="ml-1 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600" />
|
||||
<input type="checkbox" id="disable-signup" name="disable-signup" {{ if .DisableSignup }}checked="checked"{{ end }} class="ml-1 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="disable-signup" class="text-sm text-slate-300">Login required</label>
|
||||
<input type="checkbox" id="require-login" name="require-login" {{ if .RequireLogin }}checked="checked"{{ end }} class="ml-1 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
4
templates/pages/auth_form.html
vendored
4
templates/pages/auth_form.html
vendored
|
@ -8,7 +8,7 @@
|
|||
|
||||
</header>
|
||||
<main class="mt-4">
|
||||
{{ if and .signupDisabled (ne .title "Login") }}
|
||||
{{ if and .DisableSignup (ne .title "Login") }}
|
||||
<p class="italic">Administrator has disabled signing up</p>
|
||||
{{ else }}
|
||||
<div class="sm:col-span-6">
|
||||
|
@ -33,7 +33,7 @@
|
|||
<div class="flex-auto">
|
||||
<button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent border-gray-700 text-sm font-medium rounded-md shadow-sm text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">Login</button>
|
||||
</div>
|
||||
{{ if not .signupDisabled }}
|
||||
{{ if not .DisableSignup }}
|
||||
<span class="float-right text-sm py-2 underline"><a href="/register">Register instead →</a></span>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue