Skip to content

Commit

Permalink
Merge branch 'feature/setaccess' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
obcode committed Aug 10, 2022
2 parents 467dbe2 + 482e6ba commit 397a828
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 91 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ Available Commands:
delete Delete repositories.
generate Generate repositories.
help Help about any command
setaccess Set access level for exisiting repositories.
show Show config of an assignment
version Print the version number of Glabs
Expand Down
36 changes: 36 additions & 0 deletions cmd/setaccess.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cmd

import (
"fmt"

"github.com/logrusorgru/aurora/v3"
"github.com/obcode/glabs/config"
"github.com/obcode/glabs/gitlab"
"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(setaccessCmd)
setaccessCmd.Flags().StringVarP(&Level, "level", "l", "", "accesslevel (overrides config file)")
}

var (
setaccessCmd = &cobra.Command{
Use: "setaccess course assignment [groups...|students...]",
Short: "Set access level for exisiting repositories.",
Long: `Set access level for exisiting repositories.`,
Args: cobra.MinimumNArgs(2), //nolint:gomnd
Run: func(cmd *cobra.Command, args []string) {
assignmentConfig := config.GetAssignmentConfig(args[0], args[1], args[2:]...)
if len(Level) > 0 {
assignmentConfig.SetAccessLevel(Level)
}
assignmentConfig.Show()
fmt.Println(aurora.Magenta("Config okay? Press 'Enter' to continue or 'Ctrl-C' to stop ..."))
fmt.Scanln()
c := gitlab.NewClient()
c.Setaccess(assignmentConfig)
},
}
Level string
)
14 changes: 14 additions & 0 deletions config/assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,20 @@ func description(assignmentKey string) string {
return description
}

func (cfg *AssignmentConfig) SetAccessLevel(level string) {
accesslevel := Developer
switch level {
case "guest":
accesslevel = Guest
case "reporter":
accesslevel = Reporter
case "maintainer":
accesslevel = Maintainer
}

cfg.AccessLevel = accesslevel
}

func accessLevel(assignmentKey string) AccessLevel {
accesslevelIdentifier := viper.GetString(assignmentKey + ".accesslevel")

Expand Down
92 changes: 1 addition & 91 deletions gitlab/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ package gitlab
import (
"fmt"
"os"
"strings"
"time"

"github.com/logrusorgru/aurora"
"github.com/obcode/glabs/config"
"github.com/obcode/glabs/git"
"github.com/rs/zerolog/log"
"github.com/theckman/yacspin"
"github.com/xanzy/go-gitlab"
)

func (c *Client) Generate(assignmentCfg *config.AssignmentConfig) {
Expand Down Expand Up @@ -155,95 +153,7 @@ func (c *Client) generate(assignmentCfg *config.AssignmentConfig, assignmentGrou
}
}
}

for _, student := range members {
cfg.Suffix = aurora.Sprintf(aurora.Cyan(" ↪ adding member %s to %s as %s"),
aurora.Yellow(student),
aurora.Magenta(projectname),
aurora.Magenta(assignmentCfg.AccessLevel.String()),
)
spinner, err := yacspin.New(cfg)
if err != nil {
log.Debug().Err(err).Msg("cannot create spinner")
}
err = spinner.Start()
if err != nil {
log.Debug().Err(err).Msg("cannot start spinner")
}

userID, err := c.getUserID(student)
if err != nil {
if strings.Contains(student, "@") {
info, err := c.inviteByEmail(assignmentCfg, project.ID, student)
if err != nil {
spinner.StopFailMessage(fmt.Sprintf("%v", err))

err := spinner.StopFail()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
} else {

spinner.StopMessage(aurora.Sprintf(aurora.Green(info)))
err = spinner.Stop()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
}
continue
} else {
spinner.StopFailMessage(fmt.Sprintf("cannot get user id: %v", err))

err := spinner.StopFail()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
}
continue
}

info, err := c.addMember(assignmentCfg, project.ID, userID)
if err != nil {
log.Debug().Err(err).
Int("projectID", project.ID).
Int("userID", userID).
Str("student", student).
Str("course", assignmentCfg.Course).
Str("assignment", assignmentCfg.Name).
Msg("error while adding member")

spinner.StopFailMessage(fmt.Sprintf("cannot add user %s: %v", student, err))

err := spinner.StopFail()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
continue
}

spinner.StopMessage(aurora.Sprintf(aurora.Green(info)))
err = spinner.Stop()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
}

}

func (c *Client) inviteByEmail(cfg *config.AssignmentConfig, projectID int, email string) (string, error) {

m := &gitlab.InvitesOptions{
Email: &email,
AccessLevel: gitlab.AccessLevel(gitlab.AccessLevelValue(cfg.AccessLevel)),
}
resp, _, err := c.Invites.ProjectInvites(projectID, m)
if err != nil {
return "", err
}
if resp.Status != "success" {
return "", fmt.Errorf("inviting user %s failed with %s", email, resp.Message[email])
}
return fmt.Sprintf("successfully invited user %s", email), nil
c.setaccess(assignmentCfg, project, members, &cfg)
}

func (c *Client) generatePerStudent(assignmentCfg *config.AssignmentConfig, assignmentGroupID int,
Expand Down
195 changes: 195 additions & 0 deletions gitlab/setaccess.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package gitlab

import (
"fmt"
"os"
"strings"
"time"

"github.com/logrusorgru/aurora"
"github.com/obcode/glabs/config"
"github.com/rs/zerolog/log"
"github.com/theckman/yacspin"
"github.com/xanzy/go-gitlab"
)

func (c *Client) Setaccess(assignmentCfg *config.AssignmentConfig) {
assignmentGitLabGroupID, err := c.getGroupID(assignmentCfg)
if err != nil {
fmt.Printf("error: GitLab group for assignment does not exist, please create the group %s\n", assignmentCfg.URL)
os.Exit(1)
}

switch per := assignmentCfg.Per; per {
case config.PerGroup:
c.setaccessPerGroup(assignmentCfg, assignmentGitLabGroupID)
case config.PerStudent:
c.setaccessPerStudent(assignmentCfg, assignmentGitLabGroupID)
default:
fmt.Printf("it is only possible to set access levels for students oder groups, not for %v", per)
os.Exit(1)
}
}

func (c *Client) setaccess(assignmentCfg *config.AssignmentConfig,
project *gitlab.Project, members []string, cfgP *yacspin.Config) {
var cfg yacspin.Config
if cfgP == nil {
cfg = yacspin.Config{
Frequency: 100 * time.Millisecond,
CharSet: yacspin.CharSets[69],
Suffix: aurora.Sprintf(aurora.Cyan(" setting access for project %s at %s"),
aurora.Yellow(project.Name),
aurora.Magenta(assignmentCfg.URL+"/"+project.Name),
),
SuffixAutoColon: true,
StopCharacter: "✓",
StopColors: []string{"fgGreen"},
StopFailMessage: "error",
StopFailCharacter: "✗",
StopFailColors: []string{"fgRed"},
}
spinner, err := yacspin.New(cfg)
if err != nil {
log.Debug().Err(err).Msg("cannot create spinner")
}
err = spinner.Start()
if err != nil {
log.Debug().Err(err).Msg("cannot start spinner")
}
err = spinner.Stop()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
} else {
cfg = *cfgP
}

for _, student := range members {
cfg.Suffix = aurora.Sprintf(aurora.Cyan(" ↪ adding member %s to %s as %s"),
aurora.Yellow(student),
aurora.Magenta(project.Name),
aurora.Magenta(assignmentCfg.AccessLevel.String()),
)
spinner, err := yacspin.New(cfg)
if err != nil {
log.Debug().Err(err).Msg("cannot create spinner")
}
err = spinner.Start()
if err != nil {
log.Debug().Err(err).Msg("cannot start spinner")
}

userID, err := c.getUserID(student)
if err != nil {
if strings.Contains(student, "@") {
info, err := c.inviteByEmail(assignmentCfg, project.ID, student)
if err != nil {
spinner.StopFailMessage(fmt.Sprintf("%v", err))

err := spinner.StopFail()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
} else {

spinner.StopMessage(aurora.Sprintf(aurora.Green(info)))
err = spinner.Stop()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
}
continue
} else {
spinner.StopFailMessage(fmt.Sprintf("cannot get user id: %v", err))

err := spinner.StopFail()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
}
continue
}

info, err := c.addMember(assignmentCfg, project.ID, userID)
if err != nil {
log.Debug().Err(err).
Int("projectID", project.ID).
Int("userID", userID).
Str("student", student).
Str("course", assignmentCfg.Course).
Str("assignment", assignmentCfg.Name).
Msg("error while adding member")

spinner.StopFailMessage(fmt.Sprintf("cannot add user %s: %v", student, err))

err := spinner.StopFail()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
continue
}

spinner.StopMessage(aurora.Sprintf(aurora.Green(info)))
err = spinner.Stop()
if err != nil {
log.Debug().Err(err).Msg("cannot stop spinner")
}
}
}

func (c *Client) inviteByEmail(cfg *config.AssignmentConfig, projectID int, email string) (string, error) {
m := &gitlab.InvitesOptions{
Email: &email,
AccessLevel: gitlab.AccessLevel(gitlab.AccessLevelValue(cfg.AccessLevel)),
}
resp, _, err := c.Invites.ProjectInvites(projectID, m)
if err != nil {
return "", err
}
if resp.Status != "success" {
return "", fmt.Errorf("inviting user %s failed with %s", email, resp.Message[email])
}
return fmt.Sprintf("successfully invited user %s", email), nil
}

func (c *Client) setaccessPerStudent(assignmentCfg *config.AssignmentConfig, assignmentGroupID int) {
if len(assignmentCfg.Students) == 0 {
fmt.Println("no students in config for assignment found")
return
}

for _, student := range assignmentCfg.Students {
name := assignmentCfg.Name + "-" + assignmentCfg.EscapeUserName(student)
projectname := fmt.Sprintf("%s/%s", assignmentCfg.Path, name)
project, _, err := c.Projects.GetProject(
projectname,
&gitlab.GetProjectOptions{},
)
if err != nil {
fmt.Printf("cannot set access for project %s failed with %s", projectname, err)
return
}
c.setaccess(assignmentCfg, project, []string{student}, nil)
}
}

func (c *Client) setaccessPerGroup(assignmentCfg *config.AssignmentConfig, assignmentGroupID int) {
if len(assignmentCfg.Groups) == 0 {
log.Info().Str("group", assignmentCfg.Course).Msg("no groups found")
return
}

for _, grp := range assignmentCfg.Groups {
projectname := fmt.Sprintf("%s/%s-%s", assignmentCfg.Path, assignmentCfg.Name, grp.Name)
project, _, err := c.Projects.GetProject(
projectname,
&gitlab.GetProjectOptions{},
)
if err != nil {
fmt.Printf("cannot set access for project %s failed with %s", projectname, err)
return
}
c.setaccess(assignmentCfg, project, grp.Members, nil)
}
}

0 comments on commit 397a828

Please sign in to comment.