aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtz12 <koenig@fagott.pw>2016-11-13 02:46:22 (UTC)
committerrtz12 <koenig@fagott.pw>2016-11-13 02:46:22 (UTC)
commit1e92d1fd37d2fa2dd99e68082e224b8ed7d634fb (patch)
tree0fe88b192cab768247830fe4413cec5740a81d71
parent71e3b22bcc79168f0bed6e2f6b7d3e34a3b641d4 (diff)
Userspezifische Anilist-API und Koppelung implementiert
-rw-r--r--charakterin.go92
-rw-r--r--user.go45
2 files changed, 122 insertions, 15 deletions
diff --git a/charakterin.go b/charakterin.go
index 415c94b..2878f1f 100644
--- a/charakterin.go
+++ b/charakterin.go
@@ -3,13 +3,17 @@ package charakterin
3import ( 3import (
4 "database/sql" 4 "database/sql"
5 "errors" 5 "errors"
6 "fmt"
6 "io/ioutil" 7 "io/ioutil"
7 "log" 8 "log"
8 "net/http" 9 "net/http"
9 "net/url" 10 "net/url"
10 "time"
11 "regexp" 11 "regexp"
12 "time"
13
14 "fagott.pw/goanilist"
12 15
16 "github.com/julienschmidt/httprouter"
13 _ "github.com/lib/pq" 17 _ "github.com/lib/pq"
14) 18)
15 19
@@ -22,12 +26,10 @@ const (
22 26
23// Renderer wird verwendet, um die Routen (bspw. Login-Route) zu rendern. Damit bleibt Charakterin selbst ohne Template. 27// Renderer wird verwendet, um die Routen (bspw. Login-Route) zu rendern. Damit bleibt Charakterin selbst ohne Template.
24type Renderer interface { 28type Renderer interface {
25 // RenderLoginPage zeigt die Login-Seite an.
26 RenderLoginPage(w http.ResponseWriter, data map[string]interface{}) 29 RenderLoginPage(w http.ResponseWriter, data map[string]interface{})
27 // RenderRegistrationPage zeigt die Registrations-Seite an.
28 RenderRegistrationPage(w http.ResponseWriter, data map[string]interface{}) 30 RenderRegistrationPage(w http.ResponseWriter, data map[string]interface{})
29 // RenderUserSettingsPage zeigt die Seite für die Benutzereinstellungen an.
30 RenderUserSettingsPage(w http.ResponseWriter, data map[string]interface{}) 31 RenderUserSettingsPage(w http.ResponseWriter, data map[string]interface{})
32 RenderAPICouplePage(w http.ResponseWriter, data map[string]interface{})
31} 33}
32 34
33// Charakterin ist das tolle Login- und Accountmanagementsystem. 35// Charakterin ist das tolle Login- und Accountmanagementsystem.
@@ -35,6 +37,9 @@ type Charakterin struct {
35 renderer Renderer 37 renderer Renderer
36 FallbackRoute string 38 FallbackRoute string
37 Database *sql.DB 39 Database *sql.DB
40
41 anilistClientID string
42 anilistClientSecret string
38} 43}
39 44
40var reEmail, _ = regexp.Compile(`(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,})`) 45var reEmail, _ = regexp.Compile(`(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,})`)
@@ -47,9 +52,8 @@ func New(db *sql.DB) *Charakterin {
47 return nil 52 return nil
48 } 53 }
49 return &Charakterin{ 54 return &Charakterin{
50 nil, 55 FallbackRoute: "/",
51 "/", 56 Database: db,
52 db,
53 } 57 }
54} 58}
55 59
@@ -58,6 +62,11 @@ func (c *Charakterin) UseRenderer(renderer Renderer) {
58 c.renderer = renderer 62 c.renderer = renderer
59} 63}
60 64
65func (c *Charakterin) EnableAnilistAPI(id, secret string) {
66 c.anilistClientID = id
67 c.anilistClientSecret = secret
68}
69
61// DisplayLoginWithData rendert die Loginseite mit Daten (vorheriger Benutzer, Fehlermeldung) 70// DisplayLoginWithData rendert die Loginseite mit Daten (vorheriger Benutzer, Fehlermeldung)
62func (c *Charakterin) DisplayLoginWithData(w http.ResponseWriter, r *http.Request, data map[string]interface{}) { 71func (c *Charakterin) DisplayLoginWithData(w http.ResponseWriter, r *http.Request, data map[string]interface{}) {
63 if c.IsLoggedIn(r) { 72 if c.IsLoggedIn(r) {
@@ -386,6 +395,44 @@ func (c *Charakterin) Register(w http.ResponseWriter, r *http.Request) {
386 http.Redirect(w, r, c.FallbackRoute, 302) 395 http.Redirect(w, r, c.FallbackRoute, 302)
387} 396}
388 397
398func (c *Charakterin) DisplayAPICouplePage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
399 user, err := c.GetUserFromRequest(r)
400 if err != nil {
401 http.Error(w, "403", http.StatusForbidden)
402 return
403 }
404 data := make(map[string]interface{})
405 data["user"] = user
406 data["name"] = ps.ByName("type")
407 c.renderer.RenderAPICouplePage(w, data)
408}
409
410func (c *Charakterin) CoupleAPI(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
411 user, err := c.GetUserFromRequest(r)
412 if err != nil {
413 http.Error(w, "403", http.StatusForbidden)
414 return
415 }
416 body, err := readBody(r)
417 if err != nil {
418 http.Error(w, "400", http.StatusBadRequest)
419 return
420 }
421 switch ps.ByName("type") {
422 case "Anilist":
423 err = user.AnilistClient.CoupleByPin(body["code"][0])
424 }
425 if err != nil {
426 data := make(map[string]interface{})
427 data["user"] = user
428 data["name"] = ps.ByName("type")
429 data["error"] = err.Error()
430 c.renderer.RenderAPICouplePage(w, data)
431 return
432 }
433 http.Redirect(w, r, fmt.Sprintf("/user/%d", user.ID), 302)
434}
435
389func (c *Charakterin) GetUserFromRequest(r *http.Request) (*User, error) { 436func (c *Charakterin) GetUserFromRequest(r *http.Request) (*User, error) {
390 cookie, err := r.Cookie("session") 437 cookie, err := r.Cookie("session")
391 if err != nil { 438 if err != nil {
@@ -404,14 +451,22 @@ func (c *Charakterin) GetUserFromRequest(r *http.Request) (*User, error) {
404 } 451 }
405 452
406 user := &User{ 453 user := &User{
407 id, 454 ID: id,
408 name, 455 Name: name,
409 email, 456 EMail: email,
410 password, 457 Password: password,
411 displayName, 458 DisplayName: displayName,
412 lastActivity, 459 LastActivity: lastActivity,
413 isActive, 460 IsActive: isActive,
414 r.Header.Get("User-Agent"), 461 Agent: r.Header.Get("User-Agent"),
462 }
463
464 if c.anilistClientID != "" && c.anilistClientSecret != "" {
465 user.AnilistClient = goanilist.NewClient(
466 c.Database,
467 id,
468 c.anilistClientID,
469 c.anilistClientSecret)
415 } 470 }
416 471
417 return user, nil 472 return user, nil
@@ -424,6 +479,13 @@ func (c *Charakterin) GetUserByID(id int) (*User, error) {
424 if err != nil { 479 if err != nil {
425 return nil, err 480 return nil, err
426 } 481 }
482 if c.anilistClientID != "" && c.anilistClientSecret != "" {
483 user.AnilistClient = goanilist.NewClient(
484 c.Database,
485 id,
486 c.anilistClientID,
487 c.anilistClientSecret)
488 }
427 return user, nil 489 return user, nil
428} 490}
429 491
diff --git a/user.go b/user.go
index 31ec560..cea3420 100644
--- a/user.go
+++ b/user.go
@@ -3,6 +3,8 @@ package charakterin
3import ( 3import (
4 "database/sql" 4 "database/sql"
5 "time" 5 "time"
6
7 "fagott.pw/goanilist"
6) 8)
7 9
8// Ein User ist ein ganz toller Benutzer. 10// Ein User ist ein ganz toller Benutzer.
@@ -15,6 +17,9 @@ type User struct {
15 LastActivity *time.Time 17 LastActivity *time.Time
16 IsActive bool 18 IsActive bool
17 Agent string 19 Agent string
20
21 AnilistClient *goanilist.Client
22 externalServices []ExternalService
18} 23}
19 24
20// GetName gibt den Anzeigenamen oder wenn dieser nicht gesetzt ist den Benutzernamen zurück. 25// GetName gibt den Anzeigenamen oder wenn dieser nicht gesetzt ist den Benutzernamen zurück.
@@ -24,3 +29,43 @@ func (u *User) GetName() string {
24 } 29 }
25 return u.Name 30 return u.Name
26} 31}
32
33func (u *User) HasExternalServices() bool {
34 return u.AnilistClient.IsCoupled
35}
36
37func (u *User) ExternalServices() []ExternalService {
38 if u.externalServices != nil {
39 return u.externalServices
40 }
41 ss := []ExternalService{}
42 if u.AnilistClient != nil {
43 s := ExternalService{
44 Name: "Anilist",
45 IsEnabled: u.AnilistClient.IsCoupled,
46 AuthType: "copy-paste",
47 AuthorizeURL: u.AnilistClient.AuthorizeURL(),
48 CoupleURL: "/settings/api/Anilist/couple",
49 }
50 if u.AnilistClient.IsCoupled {
51 user, err := u.AnilistClient.User()
52 if err != nil {
53 s.UserName = err.Error()
54 } else {
55 s.UserName = user.DisplayName
56 }
57 }
58 ss = append(ss, s)
59 }
60 u.externalServices = ss
61 return ss
62}
63
64type ExternalService struct {
65 Name string
66 IsEnabled bool
67 AuthType string
68 AuthorizeURL string
69 CoupleURL string
70 UserName string
71}