change-vhost #47
5 changed files with 142 additions and 5 deletions
53
garage.go
53
garage.go
|
@ -270,8 +270,9 @@ func handleWebsiteInspect(w http.ResponseWriter, r *http.Request) {
|
|||
_, processErr = ctrl.Patch(bucketName, &WebsitePatch{Size: &user.Quota.WebsiteSizeBursted})
|
||||
case "delete_bucket":
|
||||
processErr = ctrl.Delete(bucketName)
|
||||
http.Redirect(w, r, "/website", http.StatusFound)
|
||||
return
|
||||
if processErr == nil {
|
||||
http.Redirect(w, r, "/website", http.StatusFound)
|
||||
}
|
||||
default:
|
||||
processErr = fmt.Errorf("Unknown action")
|
||||
}
|
||||
|
@ -295,3 +296,51 @@ func handleWebsiteInspect(w http.ResponseWriter, r *http.Request) {
|
|||
tWebsiteInspect := getTemplate("garage_website_inspect.html")
|
||||
tWebsiteInspect.Execute(w, &tpl)
|
||||
}
|
||||
|
||||
func handleWebsiteVhost(w http.ResponseWriter, r *http.Request) {
|
||||
var processErr error
|
||||
|
||||
user := RequireUserHtml(w, r)
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctrl, err := NewWebsiteController(user)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bucketName := mux.Vars(r)["bucket"]
|
||||
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
|
||||
bucket := strings.Join(r.Form["bucket"], "")
|
||||
if bucket == "" {
|
||||
bucket = strings.Join(r.Form["bucket2"], "")
|
||||
}
|
||||
|
||||
view, processErr := ctrl.Patch(bucketName, &WebsitePatch{Vhost: &bucket})
|
||||
if processErr == nil {
|
||||
http.Redirect(w, r, "/website/inspect/"+view.Name.Pretty, http.StatusFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
view, err := ctrl.Inspect(bucketName)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
describe, err := ctrl.Describe()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
tpl := &WebsiteInspectTpl{describe, view, processErr}
|
||||
tWebsiteEdit := getTemplate("garage_website_edit.html")
|
||||
tWebsiteEdit.Execute(w, &tpl)
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -161,6 +161,7 @@ func server(args []string) {
|
|||
r.HandleFunc("/website/new", handleWebsiteNew)
|
||||
r.HandleFunc("/website/configure", handleWebsiteConfigure)
|
||||
r.HandleFunc("/website/inspect/{bucket}", handleWebsiteInspect)
|
||||
r.HandleFunc("/website/vhost/{bucket}", handleWebsiteVhost)
|
||||
|
||||
r.HandleFunc("/invite/new_account", handleInviteNewAccount)
|
||||
r.HandleFunc("/invite/send_code", handleInviteSendCode)
|
||||
|
|
72
templates/garage_website_edit.html
Normal file
72
templates/garage_website_edit.html
Normal file
|
@ -0,0 +1,72 @@
|
|||
{{define "title"}}Créer un site web |{{end}}
|
||||
|
||||
{{define "body"}}
|
||||
<div class="d-flex">
|
||||
<h4>Modifier le nom de domaine</h4>
|
||||
<a class="ml-auto btn btn-link" href="/website/configure">Mes identifiants</a>
|
||||
<a class="ml-4 btn btn-info" href="/website">Mes sites webs</a>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-12">
|
||||
{{if .Err}}
|
||||
<div class="alert alert-danger">{{ .Err.Error }}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-tabs" id="proto" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="dnsint-tab" data-toggle="tab" href="#dnsint" role="tab" aria-controls="dnsint" aria-selected="true">Je n'ai pas de nom de domaine</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="dnsext-tab" data-toggle="tab" href="#dnsext" role="tab" aria-controls="dnsext" aria-selected="false">Utiliser mon propre nom de domaine</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content" id="protocols">
|
||||
|
||||
<div class="tab-pane fade show active" id="dnsint" role="tabpanel" aria-labelledby="dnsint-tab">
|
||||
<form method="POST" class="mt-4">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="bucket">Sous-domaine désiré :</label>
|
||||
<input type="text" id="bucket" name="bucket" placeholder="mon-site" class="form-control" value="" onkeyup="document.getElementById('url').value = `https://${document.getElementById('bucket').value}.web.deuxfleurs.fr`" />
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="url">Votre site sera accessible à l'URL suivante :</label>
|
||||
<input type="text" id="url" disabled="true" name="url" class="form-control" value="https://mon-site.web.deuxfleurs.fr" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<p>La première fois que vous chargerez votre site web, une erreur de certificat sera renvoyée. C'est normal, il faudra patienter quelques minutes le temps que le certificat se génère.</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Modifier le nom de domaine</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane fade show" id="dnsext" role="tabpanel" aria-labelledby="dnsext-tab">
|
||||
<form method="POST" class="mt-4">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="bucket2">Votre nom de domaine :</label>
|
||||
<input type="text" id="bucket2" name="bucket2" placeholder="example.com" class="form-control" value="" onkeyup="document.getElementById('url2').value = `https://${document.getElementById('bucket2').value}`" />
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="url2">Votre site sera accessible à l'URL suivante :</label>
|
||||
<input type="text" id="url2" disabled="true" name="url2" class="form-control" value="https://example.com" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p>Vous devez éditer votre zone DNS, souvent gérée par votre bureau d'enregistrement, comme Gandi, pour la faire pointer vers Deuxfleurs. Si vous utilisez un sous domaine (eg. <code>site.example.com</code>), une entrée <code>CNAME</code> est appropriée :</p>
|
||||
<pre>site CNAME 3600 garage.deuxfleurs.fr.</pre>
|
||||
<p>Si vous utilisez la racine de votre nom de domaine (eg. <code>example.com</code>, aussi appelée APEX), la solution dépend de votre fournisseur DNS, il vous faudra au choix une entrée <code>ALIAS</code> ou <code>CNAME</code> en fonction de ce que votre fournisseur supporte :</p>
|
||||
<pre>@ ALIAS 3600 garage.deuxfleurs.fr.</pre>
|
||||
<p>La première fois que vous chargerez votre site web, une erreur de certificat sera renvoyée. C'est normal, il faudra patienter quelques minutes le temps que le certificat se génère.</p>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-primary">Modifier le nom de domaine</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
|
@ -48,7 +48,7 @@
|
|||
<h5 class="mt-3">Quotas</h5>
|
||||
<div class="progress mt-3">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="{{ .View.Size.Current }}" aria-valuemin="0" aria-valuemax="{{ .View.Size.Max }}" style="width: {{ .View.Size.Percent }}%; min-width: 2em;">
|
||||
{{ .View.Size.Ratio }}%
|
||||
{{ .View.Size.Percent }}%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
|||
<form action="" method="post">
|
||||
<div class="btn-group" role="group" aria-label="Actions sur le site web">
|
||||
<button class="btn btn-secondary" name="action" value="increase_quota">Augmenter le quota</button>
|
||||
<a class="btn btn-secondary disabled">Changer le nom de domaine</a>
|
||||
<a class="btn btn-secondary" href="/website/vhost/{{ .View.Name.Pretty }}">Changer le nom de domaine</a>
|
||||
<button class="btn btn-danger" name="action" value="delete_bucket">Supprimer</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
17
website.go
17
website.go
|
@ -17,6 +17,8 @@ var (
|
|||
ErrCantConfigureBucket = fmt.Errorf("Unable to configure the bucket (activating website, adding quotas, etc.)")
|
||||
ErrBucketDeleteNotEmpty = fmt.Errorf("You must remove all the files before deleting a bucket")
|
||||
ErrBucketDeleteUnfinishedUpload = fmt.Errorf("You must remove all the unfinished multipart uploads before deleting a bucket")
|
||||
ErrCantChangeVhost = fmt.Errorf("Can't change the vhost to the desired value. Maybe it's already used by someone else or an internal error occured")
|
||||
ErrCantRemoveOldVhost = fmt.Errorf("The new vhost is bound to the bucket but the old one can't be removed, this is an internal error")
|
||||
)
|
||||
|
||||
type WebsiteId struct {
|
||||
|
@ -141,12 +143,24 @@ func (w *WebsiteController) Patch(pretty string, patch *WebsitePatch) (*WebsiteV
|
|||
ur := garage.NewUpdateBucketRequest()
|
||||
ur.SetQuotas(*urQuota)
|
||||
|
||||
// Call garage
|
||||
// Call garage "update bucket" function
|
||||
binfo, err = grgUpdateBucket(website.Internal, ur)
|
||||
if err != nil {
|
||||
return nil, ErrCantConfigureBucket
|
||||
}
|
||||
|
||||
// Update the alias if the vhost field is set and different
|
||||
if patch.Vhost != nil && *patch.Vhost != "" && *patch.Vhost != pretty {
|
||||
binfo, err = grgAddGlobalAlias(website.Internal, *patch.Vhost)
|
||||
if err != nil {
|
||||
return nil, ErrCantChangeVhost
|
||||
}
|
||||
binfo, err = grgDelGlobalAlias(website.Internal, pretty)
|
||||
if err != nil {
|
||||
return nil, ErrCantRemoveOldVhost
|
||||
}
|
||||
}
|
||||
|
||||
return NewWebsiteView(binfo), nil
|
||||
}
|
||||
|
||||
|
@ -233,4 +247,5 @@ func NewWebsiteView(binfo *garage.BucketInfo) *WebsiteView {
|
|||
|
||||
type WebsitePatch struct {
|
||||
Size *int64 `json:"quota_size"`
|
||||
Vhost *string `json:"vhost"`
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue