Skip to content

Commit

Permalink
feature: git first pass done, rbac: disallow users to delete/edit doc
Browse files Browse the repository at this point in the history
  • Loading branch information
hayzamjs committed Sep 7, 2024
1 parent 834dd43 commit eac012b
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 50 deletions.
77 changes: 40 additions & 37 deletions services/docs_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (

func (service *DocService) GitDeploy(docId uint) error {
doc, err := service.GetDocumentation(docId)

if err != nil {
return fmt.Errorf("failed to get documentation: %v", err)
}
Expand All @@ -35,6 +34,7 @@ func (service *DocService) GitDeploy(docId uint) error {
return fmt.Errorf("documentation path does not exist: %v", err)
}

// Build the documentation
err = utils.RunNpxCommand(docPath, "rspress", "build", "--config", "rspress.config.git.ts")
if err != nil {
return fmt.Errorf("failed to run npx command: %v", err)
Expand All @@ -47,56 +47,55 @@ func (service *DocService) GitDeploy(docId uint) error {
}
}

// Check if the remote repository exists and if its URL matches the current one
repo, err := git.PlainOpen(gitRemotePath)
if err != nil {
if err == git.ErrRepositoryNotExists {
repo, err = git.PlainClone(gitRemotePath, false, &git.CloneOptions{
URL: doc.GitRepo,
Auth: &http.BasicAuth{
Username: doc.GitUser,
Password: doc.GitPassword,
},
})
if err != nil {
return fmt.Errorf("failed to clone repository: %v", err)
if err == nil {
remote, err := repo.Remote("origin")
if err == nil {
if remote.Config().URLs[0] != doc.GitRepo {
// Repository URL has changed, remove the old repository
os.RemoveAll(gitRemotePath)
repo = nil
}
} else {
return fmt.Errorf("failed to open git repo: %v", err)
}
}

w, err := repo.Worktree()
if err != nil {
return fmt.Errorf("failed to get worktree: %v", err)
// If the repository doesn't exist or was removed, clone it
if repo == nil {
repo, err = git.PlainClone(gitRemotePath, false, &git.CloneOptions{
URL: doc.GitRepo,
Auth: &http.BasicAuth{
Username: doc.GitUser,
Password: doc.GitPassword,
},
})
if err != nil {
return fmt.Errorf("failed to clone repository: %v", err)
}
}

status, err := w.Status()
w, err := repo.Worktree()
if err != nil {
return fmt.Errorf("failed to get worktree status: %v", err)
}

if !status.IsClean() {
err = w.Reset(&git.ResetOptions{Mode: git.HardReset})
if err != nil {
return fmt.Errorf("failed to reset unstaged changes: %v", err)
}
return fmt.Errorf("failed to get worktree: %v", err)
}

// Fetch the latest changes
err = repo.Fetch(&git.FetchOptions{
Auth: &http.BasicAuth{
Username: doc.GitUser,
Password: doc.GitPassword,
},
})

if err != nil && err != git.NoErrAlreadyUpToDate {
return fmt.Errorf("failed to fetch from remote: %v", err)
}

// Check if the branch exists locally
branchRef := plumbing.NewBranchReferenceName(doc.GitBranch)
_, err = repo.Reference(branchRef, true)
branchExists := err == nil

// Checkout or create the branch
if branchExists {
err = w.Checkout(&git.CheckoutOptions{
Branch: branchRef,
Expand All @@ -111,21 +110,26 @@ func (service *DocService) GitDeploy(docId uint) error {
return fmt.Errorf("failed to checkout branch %s: %v", doc.GitBranch, err)
}

// Reset the branch to match the remote
remoteRef, err := repo.Reference(plumbing.NewRemoteReferenceName("origin", doc.GitBranch), true)

if err != nil {
return fmt.Errorf("failed to get remote reference: %v", err)
if err == plumbing.ErrReferenceNotFound {
// If the remote branch doesn't exist, we'll create it when we push
remoteRef = plumbing.NewHashReference(branchRef, plumbing.ZeroHash)
} else {
return fmt.Errorf("failed to get remote reference: %v", err)
}
}

err = w.Reset(&git.ResetOptions{
Commit: remoteRef.Hash(),
Mode: git.HardReset,
})

if err != nil {
return fmt.Errorf("failed to reset branch to match remote: %v", err)
}

// Clean the gitRemotePath
err = filepath.Walk(gitRemotePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
if os.IsNotExist(err) {
Expand All @@ -147,11 +151,11 @@ func (service *DocService) GitDeploy(docId uint) error {
}
return nil
})

if err != nil {
return fmt.Errorf("failed to clean gitRemotePath: %v", err)
}

// Copy new files
err = filepath.Walk(gitBuildPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
Expand All @@ -166,18 +170,18 @@ func (service *DocService) GitDeploy(docId uint) error {
}
return utils.CopyFile(path, destPath)
})

if err != nil {
return fmt.Errorf("failed to copy new files: %v", err)
}

// Add changes
_, err = w.Add(".")
if err != nil {
return fmt.Errorf("failed to add changes: %v", err)
}

status, err = w.Status()

// Check if there are changes to commit
status, err := w.Status()
if err != nil {
return fmt.Errorf("failed to get worktree status: %v", err)
}
Expand All @@ -187,8 +191,8 @@ func (service *DocService) GitDeploy(docId uint) error {
return nil
}

// Commit changes
updateMessage := fmt.Sprintf("Update @ %s", time.Now().Format("2006-01-02 15:04:05"))

_, err = w.Commit(updateMessage, &git.CommitOptions{
All: true,
Author: &object.Signature{
Expand All @@ -197,19 +201,18 @@ func (service *DocService) GitDeploy(docId uint) error {
When: time.Now(),
},
})

if err != nil {
return fmt.Errorf("failed to commit changes: %v", err)
}

// Push changes
err = repo.Push(&git.PushOptions{
RemoteName: "origin",
Auth: &http.BasicAuth{
Username: doc.GitUser,
Password: doc.GitPassword,
},
})

if err != nil && err != git.NoErrAlreadyUpToDate {
return fmt.Errorf("failed to push changes: %v", err)
}
Expand Down
40 changes: 29 additions & 11 deletions web/src/components/CreateDocumentModal/CreateDocModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ interface FormFieldData {
ref?: React.Ref<HTMLInputElement>;
}


const FormField: React.FC<FormFieldData> = ({
label,
placeholder,
Expand All @@ -63,22 +64,39 @@ const FormField: React.FC<FormFieldData> = ({
required = false,
ref,
}) => {
const [showPassword, setShowPassword] = useState(false);

return (
<div>
<span className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{label} {required && <span className="text-red-500 ml-1">*</span>}
</span>
<input
ref={ref}
onChange={onChange}
value={value}
type={type}
name={name}
id={name}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white"
placeholder={placeholder}
required={required}
/>
<div className="relative">
<input
ref={ref}
onChange={onChange}
value={value}
type={type === "password" && showPassword ? "text" : type}
name={name}
id={name}
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5 pr-10 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white"
placeholder={placeholder}
required={required}
/>
{type === "password" && (
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 flex items-center pr-3 bg-gray-50 dark:bg-gray-700"
>
{showPassword ? (
<Icon icon="bx:bxs-show" className="w-5 h-5 text-gray-400" />
) : (
<Icon icon="bx:bxs-hide" className="w-5 h-5 text-gray-400" />
)}
</button>
)}
</div>
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/Documentation/Documentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ export const Documentation = memo(function Documentation() {
</motion.button>
)}

{hasPermission(["all", "write"], userDetails) && (
{userDetails?.admin === true && (
<motion.button
whileHover={{ scale: 1.3 }}
title={t("edit_documentation")}
Expand All @@ -624,7 +624,7 @@ export const Documentation = memo(function Documentation() {
</motion.button>
)}

{hasPermission(["all", "delete"], userDetails) && (
{userDetails?.admin === true && (
<motion.button
whileHover={{ scale: 1.3 }}
onClick={() => {
Expand Down

0 comments on commit eac012b

Please sign in to comment.