github.com/infraboard/keyauth@v0.8.1/apps/session/impl/user.go (about) 1 package impl 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/infraboard/mcube/exception" 9 "github.com/infraboard/mcube/types/ftime" 10 "go.mongodb.org/mongo-driver/mongo" 11 12 "github.com/infraboard/keyauth/apps/session" 13 "github.com/infraboard/keyauth/apps/token" 14 ) 15 16 func (s *service) Login(ctx context.Context, tk *token.Token) (*session.Session, error) { 17 if tk.IsRefresh() { 18 sess, err := s.DescribeSession(ctx, session.NewDescribeSessionRequestWithID(tk.SessionId)) 19 if err != nil { 20 return nil, err 21 } 22 23 sess.AccessToken = tk.AccessToken 24 if err := s.updateSession(sess); err != nil { 25 return nil, err 26 } 27 return sess, nil 28 } 29 30 // 关闭之前的session 31 s.closeOldSession(ctx, tk) 32 33 sess, err := session.NewSession(tk) 34 if err != nil { 35 return nil, err 36 } 37 38 // 填充session IP信息 39 sess.IpInfo, err = s.parseRemoteIPInfo(tk.GetRemoteIp()) 40 if err != nil { 41 s.log.Errorf("parse remote ip error, %s", err) 42 } 43 44 if err := s.saveSession(sess); err != nil { 45 return nil, err 46 } 47 s.log.Infof("user(%s) session: %s login at: %d", sess.Account, sess.Id, sess.LoginAt) 48 return sess, nil 49 } 50 51 func (s *service) parseRemoteIPInfo(ip string) (*session.IPInfo, error) { 52 if ip == "" { 53 return nil, nil 54 } 55 56 info, err := s.ip.LookupIP(ip) 57 if err != nil { 58 return nil, fmt.Errorf("parse ipinfo error, %s", err) 59 } 60 61 return &session.IPInfo{ 62 CityId: info.CityID, 63 Country: info.Country, 64 Region: info.Region, 65 Province: info.Province, 66 City: info.City, 67 Isp: info.ISP, 68 }, nil 69 } 70 71 // 判断用户之前的会话是否正常退出 72 // 如果access token已经过期, 则已access token过期时间为登出数据 结束该会话 73 // 如果该会话的刷新token已经过期, 则已刷新结束时间为登出时间 结束该会话 74 // 如果token正常, 则已当前时间为登出时间 结束该会话 75 // 结束会话后, 禁用该token 76 func (s *service) closeOldSession(ctx context.Context, tk *token.Token) { 77 descReq := session.NewDescribeSessionRequestWithToken(tk) 78 sess, err := s.DescribeSession(ctx, descReq) 79 if err != nil { 80 s.log.Errorf("query session error, %s", err) 81 return 82 } 83 84 blockReq := token.NewBlockTokenRequest(sess.AccessToken, token.BlockType_OTHER_CLIENT_LOGGED_IN, "session closed by other login") 85 preTK, err := s.token.BlockToken(ctx, blockReq) 86 if err != nil { 87 s.log.Errorf("block previous token error, %s", err) 88 return 89 } 90 sess.LogoutAt = ftime.Time(time.Unix(preTK.EndAt()/1000, 0)).Timestamp() 91 sess.NamespaceId = tk.NamespaceId 92 93 if err := s.updateSession(sess); err != nil { 94 s.log.Errorf("block session error, %s", err) 95 } 96 s.log.Infof("user(%s) session: %s logout at: %d", sess.Account, sess.Id, sess.LogoutAt) 97 } 98 99 func (s *service) Logout(ctx context.Context, req *session.LogoutRequest) (*session.Session, error) { 100 descReq := session.NewDescribeSessionRequestWithID(req.SessionId) 101 sess, err := s.DescribeSession(ctx, descReq) 102 if err != nil { 103 return nil, fmt.Errorf("query session error, %s", err) 104 } 105 106 sess.LogoutAt = ftime.Now().Timestamp() 107 if err := s.updateSession(sess); err != nil { 108 s.log.Errorf("update session error, %s", err) 109 } 110 s.log.Infof("user(%s) session: %s logout at: %s", sess.Account, sess.Id, sess.LogoutAt) 111 return sess, nil 112 } 113 114 func (s *service) DescribeSession(ctx context.Context, req *session.DescribeSessionRequest) (*session.Session, error) { 115 r, err := newDescribeSession(req) 116 if err != nil { 117 return nil, err 118 } 119 120 ins := session.NewDefaultSession() 121 if err := s.col.FindOne(context.TODO(), r.FindFilter(), r.FindOptions()).Decode(ins); err != nil { 122 if err == mongo.ErrNoDocuments { 123 return nil, exception.NewNotFound("session %s not found", req) 124 } 125 126 return nil, exception.NewInternalServerError("find session %s error, %s", req.SessionId, err) 127 } 128 return ins, nil 129 } 130 131 func (s *service) QuerySession(ctx context.Context, req *session.QuerySessionRequest) (*session.Set, error) { 132 r, err := newQueryLoginLogRequest(req) 133 if err != nil { 134 return nil, exception.NewBadRequest("validate query session request error, %s", err) 135 } 136 137 resp, err := s.col.Find(context.TODO(), r.FindFilter(), r.FindOptions()) 138 139 if err != nil { 140 return nil, exception.NewInternalServerError("find session error, %s", err) 141 } 142 143 set := session.NewSessionSet() 144 // 循环 145 for resp.Next(context.TODO()) { 146 ins := session.NewDefaultSession() 147 if err := resp.Decode(ins); err != nil { 148 return nil, exception.NewInternalServerError("decode session error, error is %s", err) 149 } 150 151 set.Add(ins) 152 } 153 154 // count 155 count, err := s.col.CountDocuments(context.TODO(), r.FindFilter()) 156 if err != nil { 157 return nil, exception.NewInternalServerError("get session count error, error is %s", err) 158 } 159 set.Total = count 160 return set, nil 161 }