feat: add gitlab oauth, cleanup code

This commit is contained in:
Khairul Hidayat 2024-11-17 19:49:42 +07:00
parent a6cc450ea7
commit 83d0ed380d
29 changed files with 297 additions and 89 deletions

View File

@ -5,5 +5,10 @@ DATABASE_URL=
ENCRYPTION_KEY="" ENCRYPTION_KEY=""
# OAuth client # OAuth client
OAUTH_ENABLED=github,gitlab
GITHUB_CLIENT_ID= GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET= GITHUB_CLIENT_SECRET=
GITLAB_CLIENT_ID=
GITLAB_CLIENT_SECRET=

View File

@ -0,0 +1,43 @@
import React, { useEffect, useMemo } from "react";
import { useAuthRequest } from "expo-auth-session";
import { Button } from "tamagui";
import { useOAuthCallback } from "../hooks";
import { useServerConfig } from "@/hooks/useServerConfig";
const LoginGitlabButton = () => {
const { data: clientId } = useServerConfig("gitlab_client_id");
const discovery = useMemo(() => {
return {
authorizationEndpoint: "https://gitlab.com/oauth/authorize",
tokenEndpoint: "https://gitlab.com/oauth/token",
revocationEndpoint: "https://gitlab.com/oauth/revoke",
};
}, [clientId]);
const oauth = useOAuthCallback("gitlab");
const [request, response, promptAsync] = useAuthRequest(
{
clientId,
scopes: ["read_user"],
// redirectUri: makeRedirectUri({ scheme: appConfig.scheme }),
redirectUri: "http://localhost:8081",
},
discovery
);
useEffect(() => {
if (response?.type === "success") {
const { code } = response.params;
const verifier = request?.codeVerifier;
oauth.mutate({ code, verifier });
}
}, [response]);
return (
<Button disabled={!request} onPress={() => promptAsync()}>
Login with Gitlab
</Button>
);
};
export default LoginGitlabButton;

View File

@ -1,4 +1,4 @@
import { useMutation } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { import {
loginResultSchema, loginResultSchema,
LoginSchema, LoginSchema,
@ -45,8 +45,8 @@ export const useRegisterMutation = () => {
export const useOAuthCallback = (type: string) => { export const useOAuthCallback = (type: string) => {
return useMutation({ return useMutation({
mutationFn: async (code: string) => { mutationFn: async (params: { code: string; verifier?: string }) => {
const res = await api(`/auth/oauth/${type}/callback?code=${code}`); const res = await api(`/auth/oauth/${type}/callback`, { params });
const { data } = loginResultSchema.safeParse(res); const { data } = loginResultSchema.safeParse(res);
if (!data) { if (!data) {
throw new Error("Invalid response!"); throw new Error("Invalid response!");

View File

@ -14,6 +14,7 @@ import tamaguiConfig from "@/tamagui.config";
import { useLoginMutation } from "./hooks"; import { useLoginMutation } from "./hooks";
import LoginGithubButton from "./components/login-github"; import LoginGithubButton from "./components/login-github";
import { useServerConfig } from "@/hooks/useServerConfig"; import { useServerConfig } from "@/hooks/useServerConfig";
import LoginGitlabButton from "./components/login-gitlab";
WebBrowser.maybeCompleteAuthSession(); WebBrowser.maybeCompleteAuthSession();
@ -109,6 +110,7 @@ export default function LoginPage() {
</Text> </Text>
{oauthList.includes("github") && <LoginGithubButton />} {oauthList.includes("github") && <LoginGithubButton />}
{oauthList.includes("gitlab") && <LoginGitlabButton />}
</> </>
)} )}

View File

@ -16,21 +16,22 @@ import (
"rul.sh/vaulterm/server/utils" "rul.sh/vaulterm/server/utils"
) )
var config *oauth2.Config var githubCfg *oauth2.Config
func getGithubConfig() *oauth2.Config { func getGithubConfig() *oauth2.Config {
if config != nil { if githubCfg != nil {
return config return githubCfg
} }
config = &oauth2.Config{ githubCfg = &oauth2.Config{
ClientID: os.Getenv("GITHUB_CLIENT_ID"), ClientID: os.Getenv("GITHUB_CLIENT_ID"),
ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"),
Endpoint: github.Endpoint, Endpoint: github.Endpoint,
RedirectURL: "http://localhost:3000/auth/oauth/github/callback", // RedirectURL: "http://localhost:3000/auth/oauth/github/callback",
RedirectURL: "http://localhost:8081",
Scopes: []string{"read:user"}, Scopes: []string{"read:user"},
} }
return config return githubCfg
} }
func githubRedir(c *fiber.Ctx) error { func githubRedir(c *fiber.Ctx) error {

View File

@ -0,0 +1,147 @@
package auth
import (
"encoding/json"
"errors"
"fmt"
"io"
"log"
"os"
"strconv"
"github.com/gofiber/fiber/v2"
"golang.org/x/oauth2"
"golang.org/x/oauth2/gitlab"
"gorm.io/gorm"
"rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
)
type GitlabCfg struct {
oauth2.Config
verifier string
challenge string
}
var gitlabCfg *GitlabCfg
func getGitlabConfig() *GitlabCfg {
if gitlabCfg != nil {
return gitlabCfg
}
oauthCfg := oauth2.Config{
ClientID: os.Getenv("GITLAB_CLIENT_ID"),
ClientSecret: os.Getenv("GITLAB_CLIENT_SECRET"),
Endpoint: gitlab.Endpoint,
// RedirectURL: "http://localhost:3000/auth/oauth/gitlab/callback",
RedirectURL: "http://localhost:8081",
Scopes: []string{"read_user"},
}
verifier := oauth2.GenerateVerifier()
challenge := oauth2.S256ChallengeFromVerifier(verifier)
gitlabCfg = &GitlabCfg{
Config: oauthCfg,
verifier: verifier,
challenge: challenge,
}
return gitlabCfg
}
func gitlabRedir(c *fiber.Ctx) error {
// Redirect to Gitlab login page
url := getGitlabConfig().
AuthCodeURL("login", oauth2.S256ChallengeOption(getGitlabConfig().verifier))
return c.Redirect(url)
}
func gitlabCallback(c *fiber.Ctx) error {
cfg := getGitlabConfig()
code := c.Query("code")
verifier := c.Query("verifier")
if code == "" {
return c.Status(fiber.StatusBadRequest).SendString("Missing code")
}
if verifier == "" {
verifier = cfg.verifier
}
// Exchange code for a token
token, err := cfg.Exchange(c.Context(), code, oauth2.VerifierOption(verifier))
if err != nil {
log.Println(token, err)
return c.Status(fiber.StatusInternalServerError).SendString("Failed to exchange token")
}
// Retrieve user info
client := cfg.Client(c.Context(), token)
resp, err := client.Get("https://gitlab.com/api/v4/user")
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString("Failed to get user info")
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
return c.Status(fiber.StatusInternalServerError).
SendString(fmt.Sprintf("Gitlab API error: %s", string(body)))
}
// Parse user info
var user struct {
Username string `json:"username"`
ID int `json:"id"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
Email string `json:"email"`
}
if err := json.Unmarshal(body, &user); err != nil {
return c.Status(fiber.StatusInternalServerError).SendString("Failed to parse user info")
}
repo := NewRepository()
accountId := strconv.Itoa(user.ID)
userAccount, err := repo.FindUserAccount("gitlab", accountId)
// Register the user if the account not yet registered
if errors.Is(err, gorm.ErrRecordNotFound) {
acc := models.UserAccount{
Type: "gitlab",
AccountID: accountId,
Username: user.Username,
Email: user.Email,
}
user := models.User{
Name: user.Name,
Role: models.UserRoleUser,
Image: user.AvatarURL,
Accounts: []*models.UserAccount{&acc},
}
sessionId, err := repo.CreateUser(&user)
if err != nil {
return utils.ResponseError(c, err, 500)
}
return c.JSON(fiber.Map{
"user": user,
"sessionId": sessionId,
})
}
if err != nil {
return utils.ResponseError(c, err, 500)
}
sessionId, err := repo.CreateUserSession(&userAccount.User)
if err != nil {
return utils.ResponseError(c, err, 500)
}
return c.JSON(fiber.Map{
"user": userAccount.User,
"sessionId": sessionId,
})
}

View File

@ -3,8 +3,8 @@ package auth
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"rul.sh/vaulterm/server/db" "rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type Auth struct{ db *gorm.DB } type Auth struct{ db *gorm.DB }
@ -30,7 +30,7 @@ func (r *Auth) FindUserAccount(accountType string, accountId string) (*models.Us
} }
func (r *Auth) CreateUserSession(user *models.User) (string, error) { func (r *Auth) CreateUserSession(user *models.User) (string, error) {
sessionId, err := lib.GenerateSessionID(20) sessionId, err := utils.GenerateSessionID(20)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -19,6 +19,8 @@ func Router(app *fiber.App) {
oauth := router.Group("/oauth") oauth := router.Group("/oauth")
oauth.Get("/github", githubRedir) oauth.Get("/github", githubRedir)
oauth.Get("/github/callback", githubCallback) oauth.Get("/github/callback", githubCallback)
oauth.Get("/gitlab", gitlabRedir)
oauth.Get("/gitlab/callback", gitlabCallback)
} }
func login(c *fiber.Ctx) error { func login(c *fiber.Ctx) error {
@ -40,7 +42,7 @@ func login(c *fiber.Ctx) error {
} }
} }
if valid := lib.VerifyPassword(body.Password, user.Password); !valid { if valid := utils.VerifyPassword(body.Password, user.Password); !valid {
return &fiber.Error{ return &fiber.Error{
Code: fiber.StatusUnauthorized, Code: fiber.StatusUnauthorized,
Message: "Username or password is invalid", Message: "Username or password is invalid",
@ -59,7 +61,7 @@ func login(c *fiber.Ctx) error {
} }
func getUser(c *fiber.Ctx) error { func getUser(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
teams := []TeamWithRole{} teams := []TeamWithRole{}
for _, item := range user.Teams { for _, item := range user.Teams {
@ -96,15 +98,15 @@ func register(c *fiber.Ctx) error {
} }
} }
password, err := lib.HashPassword(body.Password) password, err := utils.HashPassword(body.Password)
if err != nil { if err != nil {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := &models.User{ user := &models.User{
Name: body.Name, Name: body.Name,
Username: body.Username, Username: &body.Username,
Email: body.Email, Email: &body.Email,
Password: password, Password: password,
Role: models.UserRoleUser, Role: models.UserRoleUser,
} }

View File

@ -3,13 +3,13 @@ package hosts
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"rul.sh/vaulterm/server/db" "rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type Hosts struct { type Hosts struct {
db *gorm.DB db *gorm.DB
User *utils.UserContext User *lib.UserContext
} }
func NewRepository(r *Hosts) *Hosts { func NewRepository(r *Hosts) *Hosts {

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils" "rul.sh/vaulterm/server/utils"
) )
@ -25,7 +26,7 @@ func getAll(c *fiber.Ctx) error {
teamId := c.Query("teamId") teamId := c.Query("teamId")
parentId := c.Query("parentId") parentId := c.Query("parentId")
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Hosts{User: user}) repo := NewRepository(&Hosts{User: user})
if teamId != "" && !user.IsInTeam(&teamId) { if teamId != "" && !user.IsInTeam(&teamId) {
@ -48,7 +49,7 @@ func create(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Hosts{User: user}) repo := NewRepository(&Hosts{User: user})
if body.TeamID != nil && !user.TeamCanWrite(body.TeamID) { if body.TeamID != nil && !user.TeamCanWrite(body.TeamID) {
@ -87,7 +88,7 @@ func update(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Hosts{User: user}) repo := NewRepository(&Hosts{User: user})
id := c.Params("id") id := c.Params("id")
@ -126,7 +127,7 @@ func update(c *fiber.Ctx) error {
} }
func delete(c *fiber.Ctx) error { func delete(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Hosts{User: user}) repo := NewRepository(&Hosts{User: user})
id := c.Params("id") id := c.Params("id")
@ -149,7 +150,7 @@ func delete(c *fiber.Ctx) error {
} }
func move(c *fiber.Ctx) error { func move(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Hosts{User: user}) repo := NewRepository(&Hosts{User: user})
// validate request // validate request

View File

@ -7,11 +7,10 @@ import (
"rul.sh/vaulterm/server/app/keychains" "rul.sh/vaulterm/server/app/keychains"
"rul.sh/vaulterm/server/lib" "rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
func tryConnect(c *fiber.Ctx, host *models.Host) (string, error) { func tryConnect(c *fiber.Ctx, host *models.Host) (string, error) {
user := utils.GetUser(c) user := lib.GetUser(c)
keyRepo := keychains.NewRepository(&keychains.Keychains{User: user}) keyRepo := keychains.NewRepository(&keychains.Keychains{User: user})
var key map[string]interface{} var key map[string]interface{}

View File

@ -3,13 +3,13 @@ package keychains
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"rul.sh/vaulterm/server/db" "rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type Keychains struct { type Keychains struct {
db *gorm.DB db *gorm.DB
User *utils.UserContext User *lib.UserContext
} }
func NewRepository(r *Keychains) *Keychains { func NewRepository(r *Keychains) *Keychains {

View File

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils" "rul.sh/vaulterm/server/utils"
) )
@ -26,7 +27,7 @@ func getAll(c *fiber.Ctx) error {
teamId := c.Query("teamId") teamId := c.Query("teamId")
withData := c.Query("withData") withData := c.Query("withData")
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Keychains{User: user}) repo := NewRepository(&Keychains{User: user})
if teamId != "" && !user.IsInTeam(&teamId) { if teamId != "" && !user.IsInTeam(&teamId) {
@ -69,7 +70,7 @@ func create(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Keychains{User: user}) repo := NewRepository(&Keychains{User: user})
if body.TeamID != nil && !user.TeamCanWrite(body.TeamID) { if body.TeamID != nil && !user.TeamCanWrite(body.TeamID) {
@ -100,7 +101,7 @@ func update(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Keychains{User: user}) repo := NewRepository(&Keychains{User: user})
id := c.Params("id") id := c.Params("id")

View File

@ -22,8 +22,9 @@ func getServerInfo(c *fiber.Ctx) error {
func getConfig(c *fiber.Ctx) error { func getConfig(c *fiber.Ctx) error {
config := fiber.Map{ config := fiber.Map{
"oauth": "github", "oauth": os.Getenv("OAUTH_ENABLED"),
"github_client_id": os.Getenv("GITHUB_CLIENT_ID"), "github_client_id": os.Getenv("GITHUB_CLIENT_ID"),
"gitlab_client_id": os.Getenv("GITLAB_CLIENT_ID"),
} }
return c.JSON(config) return c.JSON(config)
} }

View File

@ -4,13 +4,13 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"rul.sh/vaulterm/server/db" "rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type TeamMembers struct { type TeamMembers struct {
db *gorm.DB db *gorm.DB
User *utils.UserContext User *lib.UserContext
} }
func NewRepository(r *TeamMembers) *TeamMembers { func NewRepository(r *TeamMembers) *TeamMembers {

View File

@ -6,6 +6,7 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"rul.sh/vaulterm/server/app/teams" "rul.sh/vaulterm/server/app/teams"
"rul.sh/vaulterm/server/app/users" "rul.sh/vaulterm/server/app/users"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils" "rul.sh/vaulterm/server/utils"
) )
@ -20,7 +21,7 @@ func Router(app fiber.Router) {
} }
// func getAll(c *fiber.Ctx) error { // func getAll(c *fiber.Ctx) error {
// user := utils.GetUser(c) // user := lib.GetUser(c)
// repo := NewRepository(&TeamMembers{User: user}) // repo := NewRepository(&TeamMembers{User: user})
// rows, err := repo.GetAll() // rows, err := repo.GetAll()
@ -37,7 +38,7 @@ func invite(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
teamRepo := teams.NewRepository(&teams.Teams{User: user}) teamRepo := teams.NewRepository(&teams.Teams{User: user})
repo := NewRepository(&TeamMembers{User: user}) repo := NewRepository(&TeamMembers{User: user})
@ -70,7 +71,7 @@ func setRole(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
teamRepo := teams.NewRepository(&teams.Teams{User: user}) teamRepo := teams.NewRepository(&teams.Teams{User: user})
repo := NewRepository(&TeamMembers{User: user}) repo := NewRepository(&TeamMembers{User: user})
@ -103,7 +104,7 @@ func setRole(c *fiber.Ctx) error {
} }
func remove(c *fiber.Ctx) error { func remove(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
teamRepo := teams.NewRepository(&teams.Teams{User: user}) teamRepo := teams.NewRepository(&teams.Teams{User: user})
repo := NewRepository(&TeamMembers{User: user}) repo := NewRepository(&TeamMembers{User: user})

View File

@ -3,13 +3,13 @@ package teams
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"rul.sh/vaulterm/server/db" "rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type Teams struct { type Teams struct {
db *gorm.DB db *gorm.DB
User *utils.UserContext User *lib.UserContext
} }
func NewRepository(r *Teams) *Teams { func NewRepository(r *Teams) *Teams {

View File

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils" "rul.sh/vaulterm/server/utils"
) )
@ -22,7 +23,7 @@ func Router(app fiber.Router) fiber.Router {
} }
func getAll(c *fiber.Ctx) error { func getAll(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Teams{User: user}) repo := NewRepository(&Teams{User: user})
rows, err := repo.GetAll() rows, err := repo.GetAll()
@ -34,7 +35,7 @@ func getAll(c *fiber.Ctx) error {
} }
func getById(c *fiber.Ctx) error { func getById(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Teams{User: user}) repo := NewRepository(&Teams{User: user})
id := c.Params("id") id := c.Params("id")
@ -52,7 +53,7 @@ func create(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Teams{User: user}) repo := NewRepository(&Teams{User: user})
item := &models.Team{ item := &models.Team{
@ -73,7 +74,7 @@ func update(c *fiber.Ctx) error {
return utils.ResponseError(c, err, 500) return utils.ResponseError(c, err, 500)
} }
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Teams{User: user}) repo := NewRepository(&Teams{User: user})
id := c.Params("id") id := c.Params("id")
@ -98,7 +99,7 @@ func update(c *fiber.Ctx) error {
} }
func delete(c *fiber.Ctx) error { func delete(c *fiber.Ctx) error {
user := utils.GetUser(c) user := lib.GetUser(c)
repo := NewRepository(&Teams{User: user}) repo := NewRepository(&Teams{User: user})
id := c.Params("id") id := c.Params("id")

View File

@ -3,13 +3,13 @@ package users
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"rul.sh/vaulterm/server/db" "rul.sh/vaulterm/server/db"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type Users struct { type Users struct {
db *gorm.DB db *gorm.DB
User *utils.UserContext User *lib.UserContext
} }
func NewRepository(r *Users) *Users { func NewRepository(r *Users) *Users {

View File

@ -5,13 +5,12 @@ import (
"rul.sh/vaulterm/server/app/hosts" "rul.sh/vaulterm/server/app/hosts"
"rul.sh/vaulterm/server/lib" "rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
func HandleStats(c *websocket.Conn) { func HandleStats(c *websocket.Conn) {
hostId := c.Query("hostId") hostId := c.Query("hostId")
user := utils.GetUserWs(c) user := lib.GetUserWs(c)
hostRepo := hosts.NewRepository(&hosts.Hosts{User: user}) hostRepo := hosts.NewRepository(&hosts.Hosts{User: user})
data, _ := hostRepo.GetWithKeys(hostId) data, _ := hostRepo.GetWithKeys(hostId)

View File

@ -15,7 +15,7 @@ import (
func HandleTerm(c *websocket.Conn) { func HandleTerm(c *websocket.Conn) {
hostId := c.Query("hostId") hostId := c.Query("hostId")
user := utils.GetUserWs(c) user := lib.GetUserWs(c)
hostRepo := hosts.NewRepository(&hosts.Hosts{User: user}) hostRepo := hosts.NewRepository(&hosts.Hosts{User: user})
data, err := hostRepo.GetWithKeys(hostId) data, err := hostRepo.GetWithKeys(hostId)

View File

@ -2,8 +2,8 @@ package db
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"rul.sh/vaulterm/server/lib"
"rul.sh/vaulterm/server/models" "rul.sh/vaulterm/server/models"
"rul.sh/vaulterm/server/utils"
) )
type SeedFn func(*gorm.DB) error type SeedFn func(*gorm.DB) error
@ -23,7 +23,7 @@ func seedUsers(tx *gorm.DB) error {
return nil return nil
} }
testPasswd, err := lib.HashPassword("123456") testPasswd, err := utils.HashPassword("123456")
if err != nil { if err != nil {
return err return err
} }
@ -42,38 +42,38 @@ func seedUsers(tx *gorm.DB) error {
userList := []*models.User{ userList := []*models.User{
{ {
Name: "Admin", Name: "Admin",
Username: "admin", Username: utils.StringPtr("admin"),
Password: testPasswd, Password: testPasswd,
Email: "admin@mail.com", Email: utils.StringPtr("admin@mail.com"),
Role: models.UserRoleAdmin, Role: models.UserRoleAdmin,
}, },
{ // {
Name: "John Doe", // Name: "John Doe",
Username: "user", // Username: "user",
Password: testPasswd, // Password: testPasswd,
Email: "user@mail.com", // Email: "user@mail.com",
}, // },
{ // {
Name: "Mary Doe", // Name: "Mary Doe",
Username: "user2", // Username: "user2",
Password: testPasswd, // Password: testPasswd,
Email: "user2@mail.com", // Email: "user2@mail.com",
}, // },
} }
if res := tx.Create(&userList); res.Error != nil { if res := tx.Create(&userList); res.Error != nil {
return res.Error return res.Error
} }
teamMembers := []models.TeamMembers{ // teamMembers := []models.TeamMembers{
{TeamID: teams[0].ID, UserID: userList[0].ID, Role: models.TeamRoleOwner}, // {TeamID: teams[0].ID, UserID: userList[0].ID, Role: models.TeamRoleOwner},
{TeamID: teams[0].ID, UserID: userList[1].ID, Role: models.TeamRoleAdmin}, // {TeamID: teams[0].ID, UserID: userList[1].ID, Role: models.TeamRoleAdmin},
{TeamID: teams[0].ID, UserID: userList[2].ID, Role: models.TeamRoleMember}, // {TeamID: teams[0].ID, UserID: userList[2].ID, Role: models.TeamRoleMember},
} // }
if res := tx.Create(&teamMembers); res.Error != nil { // if res := tx.Create(&teamMembers); res.Error != nil {
return res.Error // return res.Error
} // }
return nil return nil
} }

View File

@ -1,4 +1,4 @@
package utils package lib
import ( import (
"github.com/gofiber/contrib/websocket" "github.com/gofiber/contrib/websocket"

View File

@ -8,6 +8,8 @@ import (
"io" "io"
"log" "log"
"net/http" "net/http"
"rul.sh/vaulterm/server/utils"
) )
type IncusServer struct { type IncusServer struct {
@ -22,7 +24,7 @@ type IncusFetchConfig struct {
} }
func (i *IncusServer) GetCertificate() (*tls.Certificate, error) { func (i *IncusServer) GetCertificate() (*tls.Certificate, error) {
return LoadClientCertificate(i.ClientCert, i.ClientKey) return utils.LoadClientCertificate(i.ClientCert, i.ClientKey)
} }
func (i *IncusServer) Fetch(method string, url string, cfg *IncusFetchConfig) ([]byte, error) { func (i *IncusServer) Fetch(method string, url string, cfg *IncusFetchConfig) ([]byte, error) {

View File

@ -3,7 +3,7 @@ package models
import ( import (
"encoding/json" "encoding/json"
"rul.sh/vaulterm/server/lib" "rul.sh/vaulterm/server/utils"
) )
const ( const (
@ -36,7 +36,7 @@ func (k *Keychain) EncryptData(data interface{}) error {
return err return err
} }
enc, err := lib.Encrypt(string(jsonData)) enc, err := utils.Encrypt(string(jsonData))
if err == nil { if err == nil {
k.Data = enc k.Data = enc
} }
@ -45,7 +45,7 @@ func (k *Keychain) EncryptData(data interface{}) error {
func (k *Keychain) DecryptData(data interface{}) error { func (k *Keychain) DecryptData(data interface{}) error {
// Decrypt stored data // Decrypt stored data
dec, err := lib.Decrypt(k.Data) dec, err := utils.Decrypt(k.Data)
if err != nil { if err != nil {
return err return err
} }

View File

@ -13,9 +13,9 @@ type User struct {
Model Model
Name string `json:"name"` Name string `json:"name"`
Username string `json:"username" gorm:"unique"` Username *string `json:"username" gorm:"unique"`
Password string `json:"-"` Password string `json:"-"`
Email string `json:"email" gorm:"unique"` Email *string `json:"email" gorm:"unique"`
Role string `json:"role" gorm:"default:user;not null;index:users_role_idx;type:varchar(8)"` Role string `json:"role" gorm:"default:user;not null;index:users_role_idx;type:varchar(8)"`
Image string `json:"image" gorm:"type:varchar(255)"` Image string `json:"image" gorm:"type:varchar(255)"`

View File

@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"rul.sh/vaulterm/server/lib"
) )
func GetDataPath(resolveFile string) string { func GetDataPath(resolveFile string) string {
@ -35,7 +33,7 @@ func CheckAndCreateEnvFile() error {
} }
// File doesn't exist, so create it // File doesn't exist, so create it
randomKey, err := lib.GenerateRandomKey() randomKey, err := GenerateRandomKey()
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,4 +1,4 @@
package lib package utils
import ( import (
"crypto/aes" "crypto/aes"

5
server/utils/string.go Normal file
View File

@ -0,0 +1,5 @@
package utils
func StringPtr(s string) *string {
return &s
}