New setting delegated_qa to store QA managers
This commit is contained in:
parent
e000778696
commit
d2f409db7a
@ -37,6 +37,7 @@ func declareTeamsRoutes(router *gin.RouterGroup) {
|
||||
|
||||
c.JSON(http.StatusOK, teams)
|
||||
})
|
||||
router.GET("/teams-associations.json", allAssociations)
|
||||
router.GET("/teams-binding", bindingTeams)
|
||||
router.GET("/teams-nginx", nginxGenTeams)
|
||||
router.POST("/disableinactiveteams", disableInactiveTeams)
|
||||
@ -282,6 +283,31 @@ func bindingTeams(c *gin.Context) {
|
||||
c.String(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
func allAssociations(c *gin.Context) {
|
||||
teams, err := fic.GetTeams()
|
||||
if err != nil {
|
||||
log.Println("Unable to GetTeams:", err.Error())
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
var ret []string
|
||||
|
||||
for _, team := range teams {
|
||||
assocs, err := pki.GetTeamAssociations(TeamsDir, team.Id)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, a := range assocs {
|
||||
ret = append(ret, a)
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
func createTeam(c *gin.Context) {
|
||||
var ut fic.Team
|
||||
err := c.ShouldBindJSON(&ut)
|
||||
|
@ -538,6 +538,13 @@ angular.module("FICApp")
|
||||
$scope.monitor = Monitor.get();
|
||||
})
|
||||
|
||||
.controller("AllTeamAssociationsController", function($scope, $http) {
|
||||
$scope.allAssociations = [];
|
||||
$http.get("api/teams-associations.json").then(function(response) {
|
||||
$scope.allAssociations = response.data;
|
||||
})
|
||||
})
|
||||
|
||||
.controller("SettingsController", function($scope, $rootScope, NextSettings, Settings, SettingsChallenge, $location, $http, $interval) {
|
||||
$scope.nextsettings = NextSettings.query();
|
||||
$scope.erase = false;
|
||||
@ -591,6 +598,29 @@ angular.module("FICApp")
|
||||
$scope.config.disablesubmitbutton = "";
|
||||
};
|
||||
|
||||
$scope.newdqa = "";
|
||||
$scope.addDelegatedQA = function() {
|
||||
if ($scope.newdqa.length) {
|
||||
if (!$scope.config.delegated_qa)
|
||||
$scope.config.delegated_qa = [];
|
||||
|
||||
$scope.config.delegated_qa.push($scope.newdqa);
|
||||
$scope.saveSettings();
|
||||
$scope.newdqa = "";
|
||||
}
|
||||
}
|
||||
$scope.dropDelegatedQA = function(member) {
|
||||
if ($scope.config.delegated_qa) {
|
||||
$scope.config.delegated_qa = [];
|
||||
|
||||
angular.forEach($scope.config.delegated_qa, function(m, k) {
|
||||
if (member == m)
|
||||
$scope.config.delegated_qa.splice(k, 1);
|
||||
});
|
||||
$scope.saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
$scope.saveChallengeInfo = function() {
|
||||
this.challenge.duration = $scope.duration;
|
||||
this.challenge.$update(function(response) {
|
||||
|
@ -264,6 +264,35 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form ng-submit="addDelegatedQA()" class="card my-3">
|
||||
<div class="card-header">
|
||||
<h3>Managers QA</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul>
|
||||
<li ng-repeat="m in config.delegated_qa">
|
||||
{{ m }}
|
||||
<button class="btn btn-sm btn-danger" type="button" ng-click="dropDelegatedQA(m)">
|
||||
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="row">
|
||||
<div class="col" ng-controller="AllTeamAssociationsController">
|
||||
<select class="form-control form-control-sm" ng-model="newdqa">
|
||||
<option ng-repeat="(i,m) in allAssociations" ng-value="m">{{ m }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col input-group">
|
||||
<input type="text" class="form-control form-control-sm" ng-model="newdqa" placeholder="Nouveau manager QA">
|
||||
<span class="input-group-append">
|
||||
<button class="btn btn-sm btn-success" ng-disabled="!newdqa.length"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form ng-submit="saveChallengeInfo()" class="card my-3">
|
||||
<div class="card-header">
|
||||
<button type="submit" class="btn btn-success float-right" title="Enregistrer les modifications aux infos du challenge"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
|
||||
|
@ -10,8 +10,11 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var Simulator string
|
||||
var TeamsDir string
|
||||
var (
|
||||
Simulator string
|
||||
TeamsDir string
|
||||
ManagerUsers []string
|
||||
)
|
||||
|
||||
func authMiddleware(access ...func(string, int64, *gin.Context) bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
@ -50,6 +53,7 @@ func authMiddleware(access ...func(string, int64, *gin.Context) bool) gin.Handle
|
||||
c.Set("LoggedTeam", teamid)
|
||||
|
||||
// We are now ready to continue
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@ -13,4 +15,18 @@ func DeclareRoutes(router *gin.RouterGroup) {
|
||||
declareThemesRoutes(apiRoutes)
|
||||
declareTodoRoutes(apiRoutes)
|
||||
declareVersionRoutes(apiRoutes)
|
||||
|
||||
apiManagerRoutes := router.Group("/api")
|
||||
apiManagerRoutes.Use(authMiddleware(func(ficteam string, teamid int64, c *gin.Context) bool {
|
||||
for _, manager := range ManagerUsers {
|
||||
if manager == ficteam {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"errmsg": "Not authorized."})
|
||||
return false
|
||||
}))
|
||||
|
||||
declareTodoManagerRoutes(apiManagerRoutes)
|
||||
}
|
||||
|
@ -12,8 +12,11 @@ func declareTodoRoutes(router *gin.RouterGroup) {
|
||||
router.GET("/qa_exercices.json", getExerciceTested)
|
||||
router.GET("/qa_mywork.json", getQAWork)
|
||||
router.GET("/qa_myexercices.json", getQAView)
|
||||
router.POST("/qa_my_exercices.json", addQAView)
|
||||
router.GET("/qa_work.json", getQATodo)
|
||||
}
|
||||
|
||||
func declareTodoManagerRoutes(router *gin.RouterGroup) {
|
||||
router.POST("/qa_my_exercices.json", addQAView)
|
||||
router.POST("/qa_work.json", createQATodo)
|
||||
}
|
||||
|
||||
@ -122,13 +125,6 @@ func getQATodo(c *gin.Context) {
|
||||
}
|
||||
|
||||
func createQATodo(c *gin.Context) {
|
||||
ficteam := c.MustGet("LoggedUser").(string)
|
||||
|
||||
if ficteam != "nemunaire" {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Restricted"})
|
||||
return
|
||||
}
|
||||
|
||||
var ut fic.QATodo
|
||||
if err := c.ShouldBindJSON(&ut); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
||||
@ -151,13 +147,6 @@ func createQATodo(c *gin.Context) {
|
||||
}
|
||||
|
||||
func addQAView(c *gin.Context) {
|
||||
ficteam := c.MustGet("LoggedUser").(string)
|
||||
|
||||
if ficteam != "nemunaire" {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Restricted"})
|
||||
return
|
||||
}
|
||||
|
||||
var ut fic.QATodo
|
||||
if err := c.ShouldBindJSON(&ut); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
|
||||
|
@ -14,11 +14,21 @@ func showVersion(c *gin.Context) {
|
||||
teamid := c.MustGet("LoggedTeam").(int64)
|
||||
ficteam := c.MustGet("LoggedUser").(string)
|
||||
|
||||
var ismanager bool
|
||||
|
||||
for _, manager := range ManagerUsers {
|
||||
if manager == ficteam {
|
||||
ismanager = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"version": 0.2,
|
||||
"auth": map[string]interface{}{
|
||||
"name": ficteam,
|
||||
"id_team": teamid,
|
||||
"is_manager": ismanager,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
"srs.epita.fr/fic-server/qa/api"
|
||||
"srs.epita.fr/fic-server/settings"
|
||||
)
|
||||
|
||||
type ResponseWriterPrefix struct {
|
||||
@ -55,6 +56,10 @@ func StripPrefix(prefix string, h http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
func reloadSettings(config *settings.Settings) {
|
||||
api.ManagerUsers = config.DelegatedQA
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Read paremeters from environment
|
||||
if v, exists := os.LookupEnv("FIC_BASEURL"); exists {
|
||||
@ -66,6 +71,7 @@ func main() {
|
||||
var dsn = flag.String("dsn", fic.DSNGenerator(), "DSN to connect to the MySQL server")
|
||||
flag.StringVar(&BaseURL, "baseurl", BaseURL, "URL prepended to each URL")
|
||||
flag.StringVar(&DevProxy, "dev", DevProxy, "Proxify traffic to this host for static assets")
|
||||
flag.StringVar(&settings.SettingsDir, "settings", "./SETTINGSDIST", "Base directory where load and save settings")
|
||||
flag.StringVar(&api.TeamsDir, "teams", "./TEAMS", "Base directory where save teams JSON files")
|
||||
flag.StringVar(&api.Simulator, "simulator", "", "Auth string to simulate (for development only)")
|
||||
flag.Parse()
|
||||
@ -86,6 +92,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
settings.LoadAndWatchSettings(path.Join(settings.SettingsDir, settings.SettingsFile), reloadSettings)
|
||||
|
||||
// Database connection
|
||||
log.Println("Opening database...")
|
||||
if err = fic.DBInit(*dsn); err != nil {
|
||||
|
@ -68,6 +68,7 @@
|
||||
<span class="d-none d-md-inline">Étapes</span>
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
{#if $auth && $auth.is_manager}
|
||||
<NavItem>
|
||||
<NavLink
|
||||
href="teams"
|
||||
@ -86,6 +87,7 @@
|
||||
<span class="d-none d-md-inline">Dépôts</span>
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
{/if}
|
||||
</Nav>
|
||||
<Nav class="ms-auto text-light" navbar>
|
||||
<NavItem class="ms-2 text-truncate">
|
||||
|
@ -1,9 +1,11 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
import { auth } from '$lib/stores/auth';
|
||||
import { themes } from '$lib/stores/themes';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
Table,
|
||||
} from 'sveltestrap';
|
||||
@ -19,6 +21,14 @@
|
||||
</script>
|
||||
|
||||
<Container class="mt-2 mb-5">
|
||||
{#if $auth && $auth.is_manager}
|
||||
<Button
|
||||
href="export"
|
||||
class="float-end"
|
||||
>
|
||||
Exporter toutes les remarques
|
||||
</Button>
|
||||
{/if}
|
||||
<h2>
|
||||
Scénarios
|
||||
</h2>
|
||||
|
@ -87,6 +87,9 @@ type Settings struct {
|
||||
GlobalTopMessageVariant string `json:"globaltopmessagevariant,omitempty"`
|
||||
// HideHeader will hide the countdown and partners block on front pages.
|
||||
HideHeader bool `json:"hide_header,omitempty"`
|
||||
|
||||
// DelegatedQA contains the users allowed to perform administrative tasks on the QA platform.
|
||||
DelegatedQA []string `json:"delegated_qa,omitempty"`
|
||||
}
|
||||
|
||||
// ExistsSettings checks if the settings file can by found at the given path.
|
||||
|
Loading…
x
Reference in New Issue
Block a user