~netlandish/links

68f8ae0c1360c2c81dc6079a8d62586cefa03cbf — Peter Sanchez 9 months ago 8718211
Working to restrict user domains to their proper org links
2 files changed, 51 insertions(+), 7 deletions(-)

M cmd/links/main.go
M domain/middleware.go
M cmd/links/main.go => cmd/links/main.go +1 -0
@@ 180,6 180,7 @@ func run() error {
			core.TimezoneContext(),
			crypto.Middleware(entropy),
			domain.DomainContext(models.DomainServiceLinks),
			domain.LinksUserDomain,
			domain.DomainRedirect,
			auth.AuthMiddleware(accounts.NewUserFetch()),
		)

M domain/middleware.go => domain/middleware.go +50 -7
@@ 75,6 75,47 @@ func DomainContext(service int) echo.MiddlewareFunc {
	}
}

// LinksUserDomain will bind a user domain to the domain organization's public links.
// It uses internal URL path mangling to produce the magic handler routing.
func LinksUserDomain(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		req := c.Request()
		domain := ForContext(req.Context())
		if domain.Level == models.DomainLevelUser && domain.OrgID.Valid {
			// Active user domain
			if req.URL.Path != "/" && req.URL.Path != "" {
				// We don't allow other paths on non system domains
				url, err := req.URL.Parse("/")
				if err != nil {
					return err
				}
				return c.Redirect(http.StatusMovedPermanently, url.String())
			}
			url, err := req.URL.Parse("/" + domain.OrgSlug.String)
			if err != nil {
				return err
			}
			req.URL = url
			c.SetRequest(req)
		}
		return next(c)
	}
}

type redir struct {
	rpath string
}

func (r redir) Redirect(path string) bool {
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}
	if strings.HasSuffix(r.rpath, "/") {
		return strings.HasPrefix(r.rpath, path)
	}
	return r.rpath == path
}

// DomainRedirect will redirect to the main links service domain if, for some reason,
// a user is trying to view service specific pages on a user domain.
func DomainRedirect(next echo.HandlerFunc) echo.HandlerFunc {


@@ 86,17 127,19 @@ func DomainRedirect(next echo.HandlerFunc) echo.HandlerFunc {
		}
		mainDomain = strings.ToLower(mainDomain)
		domain := ForContext(c.Request().Context())
		if strings.ToLower(domain.LookupName) != strings.ToLower(mainDomain) {
			redirectPaths := []string{
				"/accounts",
				"/popular",
				"/recent",
				"/tour",
		if strings.ToLower(domain.LookupName) != strings.ToLower(mainDomain) &&
			domain.Level == models.DomainLevelSystem {
			// XXX Populate this from links.InvalidSlugs or better yet, c.Echo().Routes()
			redirectPaths := []redir{
				{"/accounts/"},
				{"/popular"},
				{"/recent"},
				{"/tour"},
			}
			req := c.Request()
			rPath := req.URL.Path
			for _, path := range redirectPaths {
				if rPath == path {
				if path.Redirect(rPath) {
					mainSchema, ok := gctx.Server.Config.File.Get("gobwebs", "scheme")
					if !ok {
						return fmt.Errorf("schema not found")