add app configuration
This commit is contained in:
		
							parent
							
								
									58e6f35585
								
							
						
					
					
						commit
						c56a445c6a
					
				| @ -13,12 +13,18 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (app *application) getUserRegister(w http.ResponseWriter, r *http.Request) { | func (app *application) getUserRegister(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	if !app.config.localAuthEnabled { | ||||||
|  | 		http.Redirect(w, r, "/users/login/oidc", http.StatusFound) | ||||||
|  | 	} | ||||||
| 	form := forms.UserRegistrationForm{} | 	form := forms.UserRegistrationForm{} | ||||||
| 	data := app.newCommonData(r) | 	data := app.newCommonData(r) | ||||||
| 	views.UserRegistration("User Registration", data, form).Render(r.Context(), w) | 	views.UserRegistration("User Registration", data, form).Render(r.Context(), w) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (app *application) getUserLogin(w http.ResponseWriter, r *http.Request) { | func (app *application) getUserLogin(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	if !app.config.localAuthEnabled { | ||||||
|  | 		http.Redirect(w, r, "/users/login/oidc", http.StatusFound) | ||||||
|  | 	} | ||||||
| 	views.UserLogin("Login", app.newCommonData(r), forms.UserLoginForm{}).Render(r.Context(), w) | 	views.UserLogin("Login", app.newCommonData(r), forms.UserLoginForm{}).Render(r.Context(), w) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -94,6 +100,9 @@ func (app *application) postUserLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (app *application) userLoginOIDC(w http.ResponseWriter, r *http.Request) { | func (app *application) userLoginOIDC(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	if !app.config.oauthEnabled { | ||||||
|  | 		http.Redirect(w, r, "/users/login", http.StatusFound) | ||||||
|  | 	} | ||||||
| 	state, err := randString(16) | 	state, err := randString(16) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		app.serverError(w, r, err) | 		app.serverError(w, r, err) | ||||||
| @ -108,7 +117,7 @@ func (app *application) userLoginOIDC(w http.ResponseWriter, r *http.Request) { | |||||||
| 	setCallbackCookie(w, r, "state", state) | 	setCallbackCookie(w, r, "state", state) | ||||||
| 	setCallbackCookie(w, r, "nonce", nonce) | 	setCallbackCookie(w, r, "nonce", nonce) | ||||||
| 
 | 
 | ||||||
| 	http.Redirect(w, r, app.oauth.config.AuthCodeURL(state, oidc.Nonce(nonce)), http.StatusFound) | 	http.Redirect(w, r, app.config.oauth.config.AuthCodeURL(state, oidc.Nonce(nonce)), http.StatusFound) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (app *application) userLoginOIDCCallback(w http.ResponseWriter, r *http.Request) { | func (app *application) userLoginOIDCCallback(w http.ResponseWriter, r *http.Request) { | ||||||
| @ -122,7 +131,7 @@ func (app *application) userLoginOIDCCallback(w http.ResponseWriter, r *http.Req | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	oauth2Token, err := app.oauth.config.Exchange(r.Context(), r.URL.Query().Get("code")) | 	oauth2Token, err := app.config.oauth.config.Exchange(r.Context(), r.URL.Query().Get("code")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		app.logger.Error("Failed to exchange token") | 		app.logger.Error("Failed to exchange token") | ||||||
| 		app.serverError(w, r, err) | 		app.serverError(w, r, err) | ||||||
| @ -133,7 +142,7 @@ func (app *application) userLoginOIDCCallback(w http.ResponseWriter, r *http.Req | |||||||
| 		app.serverError(w, r, errors.New("No id_token field in oauth2 token")) | 		app.serverError(w, r, errors.New("No id_token field in oauth2 token")) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	idToken, err := app.oauth.verifier.Verify(r.Context(), rawIDToken) | 	idToken, err := app.config.oauth.verifier.Verify(r.Context(), rawIDToken) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		app.logger.Error("Failed to verify ID token") | 		app.logger.Error("Failed to verify ID token") | ||||||
| 		app.serverError(w, r, err) | 		app.serverError(w, r, err) | ||||||
|  | |||||||
| @ -113,7 +113,9 @@ func (app *application) newCommonData(r *http.Request) views.CommonData { | |||||||
| 		CSRFToken:        nosurf.Token(r), | 		CSRFToken:        nosurf.Token(r), | ||||||
| 		CurrentUser:      app.getCurrentUser(r), | 		CurrentUser:      app.getCurrentUser(r), | ||||||
| 		IsHtmx:           r.Header.Get("Hx-Request") == "true", | 		IsHtmx:           r.Header.Get("Hx-Request") == "true", | ||||||
| 		RootUrl:         app.rootUrl, | 		RootUrl:          app.config.rootUrl, | ||||||
|  | 		LocalAuthEnabled: app.config.localAuthEnabled, | ||||||
|  | 		OIDCEnabled:      app.config.oauthEnabled, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,7 +9,9 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"log/slog" | 	"log/slog" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 	"unicode" | 	"unicode" | ||||||
| @ -32,6 +34,13 @@ type applicationOauthConfig struct { | |||||||
| 	verifier   *oidc.IDTokenVerifier | 	verifier   *oidc.IDTokenVerifier | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type applicationConfig struct { | ||||||
|  | 	oauthEnabled     bool | ||||||
|  | 	localAuthEnabled bool | ||||||
|  | 	oauth            applicationOauthConfig | ||||||
|  | 	rootUrl          string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type application struct { | type application struct { | ||||||
| 	sequence          uint16 | 	sequence          uint16 | ||||||
| 	logger            *slog.Logger | 	logger            *slog.Logger | ||||||
| @ -40,21 +49,24 @@ type application struct { | |||||||
| 	guestbookComments models.GuestbookCommentModelInterface | 	guestbookComments models.GuestbookCommentModelInterface | ||||||
| 	sessionManager    *scs.SessionManager | 	sessionManager    *scs.SessionManager | ||||||
| 	formDecoder       *schema.Decoder | 	formDecoder       *schema.Decoder | ||||||
| 	oauth             applicationOauthConfig | 	config            applicationConfig | ||||||
| 	debug             bool | 	debug             bool | ||||||
| 	timezones         []string | 	timezones         []string | ||||||
| 	rootUrl           string |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 	addr := flag.String("addr", ":3000", "HTTP network address") | 	addr := flag.String("addr", ":3000", "HTTP network address") | ||||||
| 	dsn := flag.String("dsn", "guestbook.db", "data source name") | 	dsn := flag.String("dsn", "guestbook.db", "data source name") | ||||||
| 	debug := flag.Bool("debug", false, "enable debug mode") | 	debug := flag.Bool("debug", false, "enable debug mode") | ||||||
| 	root := flag.String("root", "https://localhost:3000", "root URL of application") |  | ||||||
| 	flag.Parse() | 	flag.Parse() | ||||||
| 
 | 
 | ||||||
| 	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})) | 	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})) | ||||||
| 	godotenv.Load(".env.dev") | 	godotenv.Load(".env.dev") | ||||||
|  | 	cfg, err := setupConfig(*addr) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logger.Error(err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	db, err := openDB(*dsn) | 	db, err := openDB(*dsn) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -78,18 +90,11 @@ func main() { | |||||||
| 		users:             &models.UserModel{DB: db, Settings: make(map[string]models.Setting)}, | 		users:             &models.UserModel{DB: db, Settings: make(map[string]models.Setting)}, | ||||||
| 		guestbookComments: &models.GuestbookCommentModel{DB: db}, | 		guestbookComments: &models.GuestbookCommentModel{DB: db}, | ||||||
| 		formDecoder:       formDecoder, | 		formDecoder:       formDecoder, | ||||||
|  | 		config:            cfg, | ||||||
| 		debug:             *debug, | 		debug:             *debug, | ||||||
| 		timezones:         getAvailableTimezones(), | 		timezones:         getAvailableTimezones(), | ||||||
| 		rootUrl:           *root, |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	o, err := setupOauth(app.rootUrl) |  | ||||||
| 	if err != nil { |  | ||||||
| 		logger.Error(err.Error()) |  | ||||||
| 		os.Exit(1) |  | ||||||
| 	} |  | ||||||
| 	app.oauth = o |  | ||||||
| 
 |  | ||||||
| 	err = app.users.InitializeSettingsMap() | 	err = app.users.InitializeSettingsMap() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Error(err.Error()) | 		logger.Error(err.Error()) | ||||||
| @ -137,36 +142,73 @@ func openDB(dsn string) (*sql.DB, error) { | |||||||
| 	return db, nil | 	return db, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func setupOauth(rootUrl string) (applicationOauthConfig, error) { | func setupConfig(addr string) (applicationConfig, error) { | ||||||
| 	var c applicationOauthConfig | 	var c applicationConfig | ||||||
|  | 
 | ||||||
| 	var ( | 	var ( | ||||||
|  | 		rootUrl           = os.Getenv("ROOT_URL") | ||||||
|  | 		oidcEnabled       = os.Getenv("ENABLE_OIDC") | ||||||
|  | 		localLoginEnabled = os.Getenv("ENABLE_LOCAL_LOGIN") | ||||||
| 		oauth2Provider    = os.Getenv("OAUTH2_PROVIDER") | 		oauth2Provider    = os.Getenv("OAUTH2_PROVIDER") | ||||||
| 		clientID          = os.Getenv("OAUTH2_CLIENT_ID") | 		clientID          = os.Getenv("OAUTH2_CLIENT_ID") | ||||||
| 		clientSecret      = os.Getenv("OAUTH2_CLIENT_SECRET") | 		clientSecret      = os.Getenv("OAUTH2_CLIENT_SECRET") | ||||||
| 	) | 	) | ||||||
| 	if oauth2Provider == "" || clientID == "" || clientSecret == "" { | 	if rootUrl != "" { | ||||||
| 		return applicationOauthConfig{}, errors.New("OAUTH2_PROVIDER, OAUTH2_CLIENT_ID, and OAUTH2_CLIENT_SECRET must be specified as environment variables.") | 		c.rootUrl = rootUrl | ||||||
|  | 	} else { | ||||||
|  | 		u, err := url.Parse(fmt.Sprintf("https://localhost%s", addr)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c, err | ||||||
|  | 		} | ||||||
|  | 		c.rootUrl = u.String() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	c.ctx = context.Background() | 	oauthEnabled, err := strconv.ParseBool(oidcEnabled) | ||||||
| 	provider, err := oidc.NewProvider(c.ctx, oauth2Provider) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return applicationOauthConfig{}, err | 		c.oauthEnabled = false | ||||||
| 	} | 	} | ||||||
| 	c.provider = provider | 	c.oauthEnabled = oauthEnabled | ||||||
| 	c.oidcConfig = &oidc.Config{ | 
 | ||||||
|  | 	localAuthEnabled, err := strconv.ParseBool(localLoginEnabled) | ||||||
|  | 	if err != nil { | ||||||
|  | 		c.localAuthEnabled = true | ||||||
|  | 	} | ||||||
|  | 	c.localAuthEnabled = localAuthEnabled | ||||||
|  | 
 | ||||||
|  | 	if !c.oauthEnabled && !c.localAuthEnabled { | ||||||
|  | 		return c, errors.New("Either ENABLE_OIDC or ENABLE_LOCAL_LOGIN must be set to true") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// if OIDC is disabled, no more configuration needs to be read | ||||||
|  | 	if !oauthEnabled { | ||||||
|  | 		return c, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var o applicationOauthConfig | ||||||
|  | 	if oauth2Provider == "" || clientID == "" || clientSecret == "" { | ||||||
|  | 		return c, errors.New("OAUTH2_PROVIDER, OAUTH2_CLIENT_ID, and OAUTH2_CLIENT_SECRET must be specified as environment variables.") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	o.ctx = context.Background() | ||||||
|  | 	provider, err := oidc.NewProvider(o.ctx, oauth2Provider) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return c, err | ||||||
|  | 	} | ||||||
|  | 	o.provider = provider | ||||||
|  | 	o.oidcConfig = &oidc.Config{ | ||||||
| 		ClientID: clientID, | 		ClientID: clientID, | ||||||
| 	} | 	} | ||||||
| 	c.verifier = provider.Verifier(c.oidcConfig) | 	o.verifier = provider.Verifier(o.oidcConfig) | ||||||
| 	c.config = oauth2.Config{ | 	o.config = oauth2.Config{ | ||||||
| 		ClientID:     clientID, | 		ClientID:     clientID, | ||||||
| 		ClientSecret: clientSecret, | 		ClientSecret: clientSecret, | ||||||
| 		Endpoint:     provider.Endpoint(), | 		Endpoint:     provider.Endpoint(), | ||||||
| 		RedirectURL:  fmt.Sprintf("%s/users/login/oidc/callback", rootUrl), | 		RedirectURL:  fmt.Sprintf("%s/users/login/oidc/callback", c.rootUrl), | ||||||
| 		Scopes:       []string{oidc.ScopeOpenID, "profile", "email"}, | 		Scopes:       []string{oidc.ScopeOpenID, "profile", "email"}, | ||||||
| 	} | 	} | ||||||
| 	return c, nil |  | ||||||
| 
 | 
 | ||||||
|  | 	c.oauth = o | ||||||
|  | 	return c, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getAvailableTimezones() []string { | func getAvailableTimezones() []string { | ||||||
|  | |||||||
| @ -13,6 +13,8 @@ type CommonData struct { | |||||||
| 	CurrentUser      *models.User | 	CurrentUser      *models.User | ||||||
| 	IsHtmx           bool | 	IsHtmx           bool | ||||||
| 	RootUrl          string | 	RootUrl          string | ||||||
|  | 	LocalAuthEnabled bool | ||||||
|  | 	OIDCEnabled      bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func shortIdToSlug(shortId uint64) string { | func shortIdToSlug(shortId uint64) string { | ||||||
| @ -52,7 +54,9 @@ templ topNav(data CommonData) { | |||||||
| 				<a href="/users/settings">Settings</a> |  | 				<a href="/users/settings">Settings</a> |  | ||||||
| 				<a href="#" hx-post="/users/logout" hx-headers={ hxHeaders }>Logout</a> | 				<a href="#" hx-post="/users/logout" hx-headers={ hxHeaders }>Logout</a> | ||||||
| 			} else { | 			} else { | ||||||
|  | 				if data.LocalAuthEnabled { | ||||||
| 					<a href="/users/register">Create an Account</a> |  | 					<a href="/users/register">Create an Account</a> |  | ||||||
|  | 				} | ||||||
| 				<a href="/users/login">Login</a> | 				<a href="/users/login">Login</a> | ||||||
| 			} | 			} | ||||||
| 		</div> | 		</div> | ||||||
|  | |||||||
| @ -21,6 +21,8 @@ type CommonData struct { | |||||||
| 	CurrentUser      *models.User | 	CurrentUser      *models.User | ||||||
| 	IsHtmx           bool | 	IsHtmx           bool | ||||||
| 	RootUrl          string | 	RootUrl          string | ||||||
|  | 	LocalAuthEnabled bool | ||||||
|  | 	OIDCEnabled      bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func shortIdToSlug(shortId uint64) string { | func shortIdToSlug(shortId uint64) string { | ||||||
| @ -102,7 +104,7 @@ func topNav(data CommonData) templ.Component { | |||||||
| 			var templ_7745c5c3_Var3 string | 			var templ_7745c5c3_Var3 string | ||||||
| 			templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.CurrentUser.Username) | 			templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.CurrentUser.Username) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 45, Col: 40} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 47, Col: 40} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| @ -121,7 +123,7 @@ func topNav(data CommonData) templ.Component { | |||||||
| 			var templ_7745c5c3_Var4 string | 			var templ_7745c5c3_Var4 string | ||||||
| 			templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(hxHeaders) | 			templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(hxHeaders) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 53, Col: 62} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 55, Col: 62} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| @ -132,12 +134,18 @@ func topNav(data CommonData) templ.Component { | |||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a href=\"/users/register\">Create an Account</a> |  <a href=\"/users/login\">Login</a>") | 			if data.LocalAuthEnabled { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a href=\"/users/register\">Create an Account</a> | ") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></nav>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " <a href=\"/users/login\">Login</a>") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></nav>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| @ -166,7 +174,7 @@ func commonFooter() templ.Component { | |||||||
| 			templ_7745c5c3_Var5 = templ.NopComponent | 			templ_7745c5c3_Var5 = templ.NopComponent | ||||||
| 		} | 		} | ||||||
| 		ctx = templ.ClearChildren(ctx) | 		ctx = templ.ClearChildren(ctx) | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<footer><p>A <a href=\"https://32bit.cafe\">32bit.cafe</a> Project</p></footer>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<footer><p>A <a href=\"https://32bit.cafe\">32bit.cafe</a> Project</p></footer>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| @ -195,20 +203,20 @@ func base(title string, data CommonData) templ.Component { | |||||||
| 			templ_7745c5c3_Var6 = templ.NopComponent | 			templ_7745c5c3_Var6 = templ.NopComponent | ||||||
| 		} | 		} | ||||||
| 		ctx = templ.ClearChildren(ctx) | 		ctx = templ.ClearChildren(ctx) | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<!doctype html><html lang=\"en\"><head><title>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<!doctype html><html lang=\"en\"><head><title>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		var templ_7745c5c3_Var7 string | 		var templ_7745c5c3_Var7 string | ||||||
| 		templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(title) | 		templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(title) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 72, Col: 17} | 			return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 76, Col: 17} | ||||||
| 		} | 		} | ||||||
| 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) | 		_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " - webweav.ing</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"/static/css/classless.min.css\" rel=\"stylesheet\"><link href=\"/static/css/style.css\" rel=\"stylesheet\"><script src=\"/static/js/htmx.min.js\"></script></head><body>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, " - webweav.ing</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"/static/css/classless.min.css\" rel=\"stylesheet\"><link href=\"/static/css/style.css\" rel=\"stylesheet\"><script src=\"/static/js/htmx.min.js\"></script></head><body>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| @ -220,25 +228,25 @@ func base(title string, data CommonData) templ.Component { | |||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<main>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<main>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		if data.Flash != "" { | 		if data.Flash != "" { | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"flash\">") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"flash\">") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var8 string | 			var templ_7745c5c3_Var8 string | ||||||
| 			templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(data.Flash) | 			templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(data.Flash) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 84, Col: 36} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 88, Col: 36} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| @ -247,7 +255,7 @@ func base(title string, data CommonData) templ.Component { | |||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</main>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</main>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| @ -255,7 +263,7 @@ func base(title string, data CommonData) templ.Component { | |||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
| 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</body></html>") | 		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</body></html>") | ||||||
| 		if templ_7745c5c3_Err != nil { | 		if templ_7745c5c3_Err != nil { | ||||||
| 			return templ_7745c5c3_Err | 			return templ_7745c5c3_Err | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -31,7 +31,9 @@ templ UserLogin(title string, data CommonData, form forms.UserLoginForm) { | |||||||
| 			</div> | 			</div> | ||||||
| 			<div> | 			<div> | ||||||
| 				<input type="submit" value="Login"/> | 				<input type="submit" value="Login"/> | ||||||
|  | 				if data.OIDCEnabled { | ||||||
| 					<a href="/users/login/oidc">Login with SSO</a> | 					<a href="/users/login/oidc">Login with SSO</a> | ||||||
|  | 				} | ||||||
| 			</div> | 			</div> | ||||||
| 		</form> | 		</form> | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -143,7 +143,17 @@ func UserLogin(title string, data CommonData, form forms.UserLoginForm) templ.Co | |||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<input type=\"password\" name=\"password\"></div><div><input type=\"submit\" value=\"Login\"> <a href=\"/users/login/oidc\">Login with SSO</a></div></form>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<input type=\"password\" name=\"password\"></div><div><input type=\"submit\" value=\"Login\"> ") | ||||||
|  | 			if templ_7745c5c3_Err != nil { | ||||||
|  | 				return templ_7745c5c3_Err | ||||||
|  | 			} | ||||||
|  | 			if data.OIDCEnabled { | ||||||
|  | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<a href=\"/users/login/oidc\">Login with SSO</a>") | ||||||
|  | 				if templ_7745c5c3_Err != nil { | ||||||
|  | 					return templ_7745c5c3_Err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div></form>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| @ -190,130 +200,130 @@ func UserRegistration(title string, data CommonData, form forms.UserRegistration | |||||||
| 				}() | 				}() | ||||||
| 			} | 			} | ||||||
| 			ctx = templ.InitializeContext(ctx) | 			ctx = templ.InitializeContext(ctx) | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<h1>User Registration</h1><form action=\"/users/register\" method=\"post\"><input type=\"hidden\" name=\"csrf_token\" value=\"") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<h1>User Registration</h1><form action=\"/users/register\" method=\"post\"><input type=\"hidden\" name=\"csrf_token\" value=\"") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var10 string | 			var templ_7745c5c3_Var10 string | ||||||
| 			templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken) | 			templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 44, Col: 64} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 46, Col: 64} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\"><div>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"><div>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			error, exists := form.FieldErrors["name"] | 			error, exists := form.FieldErrors["name"] | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<label for=\"username\">Username: </label> ") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<label for=\"username\">Username: </label> ") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			if exists { | 			if exists { | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<label class=\"error\">") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<label class=\"error\">") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				var templ_7745c5c3_Var11 string | 				var templ_7745c5c3_Var11 string | ||||||
| 				templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(error) | 				templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(error) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 49, Col: 33} | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 51, Col: 33} | ||||||
| 				} | 				} | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</label> ") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</label> ") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<input type=\"text\" name=\"username\" id=\"username\" value=\"") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<input type=\"text\" name=\"username\" id=\"username\" value=\"") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var12 string | 			var templ_7745c5c3_Var12 string | ||||||
| 			templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name) | 			templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 51, Col: 70} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 53, Col: 70} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" required></div><div>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" required></div><div>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			error, exists = form.FieldErrors["email"] | 			error, exists = form.FieldErrors["email"] | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<label for=\"email\">Email: </label> ") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<label for=\"email\">Email: </label> ") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			if exists { | 			if exists { | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<label class=\"error\">") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<label class=\"error\">") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				var templ_7745c5c3_Var13 string | 				var templ_7745c5c3_Var13 string | ||||||
| 				templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(error) | 				templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(error) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 57, Col: 33} | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 59, Col: 33} | ||||||
| 				} | 				} | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</label> ") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</label> ") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<input type=\"text\" name=\"email\" id=\"email\" value=\"") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<input type=\"text\" name=\"email\" id=\"email\" value=\"") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var14 string | 			var templ_7745c5c3_Var14 string | ||||||
| 			templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email) | 			templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 59, Col: 65} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 61, Col: 65} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" required></div><div>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\" required></div><div>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			error, exists = form.FieldErrors["password"] | 			error, exists = form.FieldErrors["password"] | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<label for=\"password\">Password: </label> ") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<label for=\"password\">Password: </label> ") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			if exists { | 			if exists { | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<label class=\"error\">") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<label class=\"error\">") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				var templ_7745c5c3_Var15 string | 				var templ_7745c5c3_Var15 string | ||||||
| 				templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(error) | 				templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(error) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 65, Col: 33} | 					return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 67, Col: 33} | ||||||
| 				} | 				} | ||||||
| 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) | 				_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</label> ") | 				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</label> ") | ||||||
| 				if templ_7745c5c3_Err != nil { | 				if templ_7745c5c3_Err != nil { | ||||||
| 					return templ_7745c5c3_Err | 					return templ_7745c5c3_Err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<input type=\"password\" name=\"password\" id=\"password\"></div><div><input type=\"submit\" value=\"Register\"></div></form>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<input type=\"password\" name=\"password\" id=\"password\"></div><div><input type=\"submit\" value=\"Register\"></div></form>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| @ -360,33 +370,33 @@ func UserProfile(title string, data CommonData, user models.User) templ.Componen | |||||||
| 				}() | 				}() | ||||||
| 			} | 			} | ||||||
| 			ctx = templ.InitializeContext(ctx) | 			ctx = templ.InitializeContext(ctx) | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<h1>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<h1>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var18 string | 			var templ_7745c5c3_Var18 string | ||||||
| 			templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username) | 			templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 78, Col: 21} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 80, Col: 21} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</h1><p>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</h1><p>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var19 string | 			var templ_7745c5c3_Var19 string | ||||||
| 			templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email) | 			templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 79, Col: 17} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 81, Col: 17} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</p>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</p>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| @ -434,89 +444,89 @@ func UserSettingsView(data CommonData, timezones []string) templ.Component { | |||||||
| 				}() | 				}() | ||||||
| 			} | 			} | ||||||
| 			ctx = templ.InitializeContext(ctx) | 			ctx = templ.InitializeContext(ctx) | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<div><h1>User Settings</h1><form hx-put=\"/users/settings\"><input type=\"hidden\" name=\"csrf_token\" value=\"") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "<div><h1>User Settings</h1><form hx-put=\"/users/settings\"><input type=\"hidden\" name=\"csrf_token\" value=\"") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			var templ_7745c5c3_Var22 string | 			var templ_7745c5c3_Var22 string | ||||||
| 			templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken) | 			templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 89, Col: 65} | 				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 91, Col: 65} | ||||||
| 			} | 			} | ||||||
| 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) | 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\"> <label>Local Timezone</label> <select name=\"timezones\" id=\"timezone-select\">") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\"> <label>Local Timezone</label> <select name=\"timezones\" id=\"timezone-select\">") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
| 			for _, tz := range timezones { | 			for _, tz := range timezones { | ||||||
| 				if tz == user.Settings.LocalTimezone.String() { | 				if tz == user.Settings.LocalTimezone.String() { | ||||||
| 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "<option value=\"") | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<option value=\"") | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					var templ_7745c5c3_Var23 string | 					var templ_7745c5c3_Var23 string | ||||||
| 					templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | 					templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 94, Col: 25} | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 96, Col: 25} | ||||||
| 					} | 					} | ||||||
| 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\" selected=\"true\">") | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" selected=\"true\">") | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					var templ_7745c5c3_Var24 string | 					var templ_7745c5c3_Var24 string | ||||||
| 					templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | 					templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 94, Col: 48} | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 96, Col: 48} | ||||||
| 					} | 					} | ||||||
| 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</option>") | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</option>") | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<option value=\"") | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<option value=\"") | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					var templ_7745c5c3_Var25 string | 					var templ_7745c5c3_Var25 string | ||||||
| 					templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | 					templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 96, Col: 25} | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 98, Col: 25} | ||||||
| 					} | 					} | ||||||
| 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\">") | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\">") | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					var templ_7745c5c3_Var26 string | 					var templ_7745c5c3_Var26 string | ||||||
| 					templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | 					templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(tz) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 96, Col: 32} | 						return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 98, Col: 32} | ||||||
| 					} | 					} | ||||||
| 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) | 					_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</option>") | 					templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</option>") | ||||||
| 					if templ_7745c5c3_Err != nil { | 					if templ_7745c5c3_Err != nil { | ||||||
| 						return templ_7745c5c3_Err | 						return templ_7745c5c3_Err | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</select> <input type=\"submit\" value=\"Submit\"></form></div>") | 			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</select> <input type=\"submit\" value=\"Submit\"></form></div>") | ||||||
| 			if templ_7745c5c3_Err != nil { | 			if templ_7745c5c3_Err != nil { | ||||||
| 				return templ_7745c5c3_Err | 				return templ_7745c5c3_Err | ||||||
| 			} | 			} | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user