Ver código fonte

feat(vpn): impl. server and ca cert expiration indicators

Expiration indicators for server and CA is added to the both webui and cli.

Closes #59
Mustafa Arici 7 anos atrás
pai
commit
fbc7ddb4e8

+ 60 - 51
api/pb/user.pb.go

@@ -336,6 +336,7 @@ type UserResponse_User struct {
 	ConnectedSince     string `protobuf:"bytes,10,opt,name=connected_since,json=connectedSince" json:"connected_since,omitempty"`
 	BytesSent          uint64 `protobuf:"varint,11,opt,name=bytes_sent,json=bytesSent" json:"bytes_sent,omitempty"`
 	BytesReceived      uint64 `protobuf:"varint,12,opt,name=bytes_received,json=bytesReceived" json:"bytes_received,omitempty"`
+	ExpiresAt          string `protobuf:"bytes,13,opt,name=expires_at,json=expiresAt" json:"expires_at,omitempty"`
 }
 
 func (m *UserResponse_User) Reset()                    { *m = UserResponse_User{} }
@@ -427,6 +428,13 @@ func (m *UserResponse_User) GetBytesReceived() uint64 {
 	return 0
 }
 
+func (m *UserResponse_User) GetExpiresAt() string {
+	if m != nil {
+		return m.ExpiresAt
+	}
+	return ""
+}
+
 type UserGenConfigResponse struct {
 	ClientConfig string `protobuf:"bytes,1,opt,name=client_config,json=clientConfig" json:"client_config,omitempty"`
 }
@@ -698,56 +706,57 @@ var _UserService_serviceDesc = grpc.ServiceDesc{
 func init() { proto.RegisterFile("user.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-	// 809 bytes of a gzipped FileDescriptorProto
+	// 825 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xdd, 0x6e, 0xe3, 0x44,
-	0x14, 0x80, 0x6b, 0xd7, 0x71, 0xe3, 0x93, 0xb4, 0x75, 0x27, 0x2d, 0xeb, 0x86, 0x5d, 0xc8, 0x1a,
-	0x01, 0xd1, 0x22, 0x25, 0x10, 0xf6, 0x02, 0xad, 0x10, 0x52, 0x94, 0x85, 0x50, 0x09, 0x9c, 0xc5,
-	0xd9, 0x55, 0x2f, 0x2d, 0xc7, 0x3e, 0x09, 0x23, 0xa5, 0x63, 0xe3, 0x99, 0x24, 0xe2, 0x16, 0x89,
-	0x27, 0x80, 0x57, 0x41, 0x3c, 0x08, 0xaf, 0xc0, 0x4b, 0x70, 0x87, 0x66, 0xc6, 0x49, 0x48, 0x49,
-	0x51, 0x2e, 0xb8, 0x9b, 0xf3, 0xf7, 0xcd, 0xf1, 0x9c, 0x1f, 0x03, 0x2c, 0x38, 0x16, 0x9d, 0xbc,
-	0xc8, 0x44, 0x46, 0xcc, 0x7c, 0xd2, 0x7c, 0x3c, 0xcb, 0xb2, 0xd9, 0x1c, 0xbb, 0x71, 0x4e, 0xbb,
-	0x31, 0x63, 0x99, 0x88, 0x05, 0xcd, 0x18, 0xd7, 0x1e, 0xfe, 0x05, 0x9c, 0xbf, 0xe1, 0x58, 0x7c,
-	0x43, 0xb9, 0x08, 0xf1, 0x87, 0x05, 0x72, 0xe1, 0xff, 0x6a, 0xc0, 0x85, 0xd4, 0x0d, 0x0a, 0x8c,
-	0x05, 0x96, 0x5a, 0xd2, 0x84, 0xaa, 0x04, 0xb3, 0xf8, 0x0e, 0x3d, 0xa3, 0x65, 0xb4, 0x9d, 0x70,
-	0x23, 0x4b, 0x5b, 0x1e, 0x73, 0xbe, 0xca, 0x8a, 0xd4, 0x33, 0xb5, 0x6d, 0x2d, 0x93, 0x06, 0x54,
-	0x58, 0x16, 0xcd, 0x56, 0xde, 0x71, 0xcb, 0x68, 0x57, 0x43, 0x8b, 0x65, 0xc3, 0x15, 0x79, 0x04,
-	0x27, 0xdf, 0x67, 0x5c, 0x44, 0x34, 0xf5, 0xac, 0x96, 0xd1, 0x3e, 0x0d, 0x6d, 0x29, 0xde, 0xa4,
-	0xe4, 0x1a, 0xaa, 0x94, 0x47, 0x71, 0x7a, 0x47, 0x99, 0x57, 0x51, 0x01, 0x27, 0x94, 0xf7, 0xa5,
-	0xe8, 0xff, 0x76, 0xac, 0xd3, 0x7a, 0x93, 0xa7, 0xff, 0x43, 0x5a, 0xcf, 0xc1, 0x9e, 0xad, 0xf2,
-	0x02, 0xa7, 0x2a, 0xaf, 0xb3, 0xde, 0xe3, 0x4e, 0x3e, 0xe9, 0xfc, 0x0b, 0xdf, 0x19, 0xde, 0xbe,
-	0x2a, 0x70, 0x1a, 0x96, 0xbe, 0x0f, 0xe7, 0xdd, 0x87, 0x1a, 0x97, 0x0f, 0x9b, 0x44, 0x8a, 0x59,
-	0x51, 0xcc, 0xd6, 0x7e, 0xe6, 0x58, 0x39, 0x2a, 0x2e, 0xf0, 0xcd, 0x99, 0x7c, 0x01, 0xa0, 0xbe,
-	0x5b, 0x13, 0x6c, 0x45, 0x78, 0x77, 0x3f, 0x41, 0x3d, 0x88, 0x02, 0x38, 0xf1, 0xfa, 0xe8, 0x7f,
-	0x00, 0xb6, 0xce, 0x96, 0x00, 0xd8, 0xc1, 0xe8, 0x55, 0xf8, 0xe5, 0x57, 0xee, 0x11, 0xa9, 0x82,
-	0x15, 0x8c, 0x86, 0xb7, 0xae, 0x41, 0x6c, 0x30, 0x87, 0xb7, 0xae, 0xe9, 0x7f, 0x06, 0xb0, 0xcd,
-	0x80, 0xb8, 0x50, 0xd7, 0xbe, 0xe3, 0xd7, 0xfd, 0xd7, 0x37, 0x03, 0xf7, 0x88, 0xd4, 0xa1, 0x1a,
-	0x8c, 0x4a, 0xc9, 0x90, 0xac, 0xf2, 0x6c, 0xfa, 0xcf, 0xc1, 0xd9, 0xdc, 0x4c, 0xce, 0xa1, 0xa6,
-	0x03, 0xfb, 0x2f, 0xbf, 0xbd, 0x09, 0xdc, 0x23, 0x52, 0x83, 0x93, 0x60, 0xa4, 0x05, 0x83, 0x38,
-	0x50, 0xd1, 0x47, 0xd3, 0xef, 0xea, 0xb2, 0xbd, 0xc4, 0x39, 0x1e, 0x54, 0x36, 0xbf, 0x03, 0xae,
-	0x0c, 0x08, 0x91, 0xe1, 0xea, 0x10, 0xff, 0x1e, 0x5c, 0x4a, 0xff, 0x21, 0xb2, 0x41, 0xc6, 0xa6,
-	0x74, 0x76, 0x48, 0xcc, 0xef, 0xc7, 0x50, 0xd7, 0x97, 0xf0, 0x3c, 0x63, 0x1c, 0xc9, 0x47, 0x50,
-	0x91, 0x46, 0xee, 0x19, 0xad, 0xe3, 0x76, 0xad, 0x77, 0xb5, 0x7e, 0xf8, 0xb5, 0x83, 0x16, 0xb4,
-	0x4f, 0xf3, 0x2f, 0x13, 0x2c, 0x29, 0xff, 0x67, 0xf7, 0x7d, 0x0c, 0x97, 0x1c, 0x8b, 0x25, 0x16,
-	0x11, 0xc7, 0x82, 0xc6, 0xf3, 0x88, 0x2d, 0xee, 0x26, 0x58, 0x94, 0x9d, 0x48, 0xb4, 0x6d, 0xac,
-	0x4c, 0x81, 0xb2, 0x10, 0x02, 0x56, 0x82, 0x85, 0x50, 0x1d, 0xe9, 0x84, 0xea, 0x4c, 0x9e, 0x00,
-	0x24, 0x6a, 0x0e, 0xd3, 0x28, 0x16, 0xaa, 0xe9, 0x9c, 0xd0, 0x29, 0x35, 0x7d, 0x41, 0xae, 0xc0,
-	0xa6, 0x79, 0xc4, 0x50, 0xa8, 0x96, 0x73, 0xc2, 0x0a, 0xcd, 0x03, 0x14, 0xdb, 0xa1, 0xb3, 0xf7,
-	0x0f, 0xdd, 0xc9, 0x83, 0x43, 0x57, 0xdd, 0x19, 0x3a, 0xf2, 0x14, 0xea, 0x94, 0x47, 0x49, 0xc6,
-	0x18, 0x26, 0x02, 0x53, 0xcf, 0x51, 0xe6, 0x1a, 0xe5, 0x83, 0xb5, 0x8a, 0x7c, 0x08, 0xe7, 0x1b,
-	0x7b, 0xc4, 0x29, 0x4b, 0xd0, 0x03, 0x95, 0xcb, 0xd9, 0x46, 0x3d, 0x96, 0x5a, 0xf9, 0x29, 0x93,
-	0x1f, 0x05, 0xf2, 0x88, 0x23, 0x13, 0x5e, 0xad, 0x65, 0xb4, 0xad, 0xd0, 0x51, 0x9a, 0x31, 0x32,
-	0x41, 0xde, 0x87, 0x33, 0x6d, 0x2e, 0x30, 0x41, 0xba, 0xc4, 0xd4, 0xab, 0x2b, 0x97, 0x53, 0xa5,
-	0x0d, 0x4b, 0xa5, 0xff, 0x39, 0x5c, 0xdd, 0xab, 0x76, 0x59, 0xc1, 0xf7, 0xe0, 0x34, 0x99, 0x53,
-	0x64, 0x42, 0xa6, 0x3b, 0xa5, 0xb3, 0xb2, 0x20, 0x75, 0xad, 0xd4, 0xce, 0xbd, 0x9f, 0x2d, 0xa8,
-	0xc9, 0xf0, 0x31, 0x16, 0x4b, 0x9a, 0x20, 0xf9, 0x1a, 0x2c, 0xb9, 0xfa, 0x48, 0x63, 0x5d, 0xef,
-	0x7f, 0x2c, 0xc2, 0xa6, 0x7b, 0xbf, 0x09, 0xfc, 0xeb, 0x9f, 0xfe, 0xf8, 0xf3, 0x17, 0xb3, 0x41,
-	0x2e, 0xd4, 0x36, 0x5d, 0x7e, 0xd2, 0x95, 0xd5, 0xee, 0xce, 0x25, 0xe1, 0x3b, 0xb0, 0xf5, 0xc2,
-	0x24, 0x9b, 0xde, 0xd9, 0x59, 0xa0, 0x7b, 0x68, 0xef, 0x28, 0x9a, 0xe7, 0x37, 0x76, 0x68, 0xba,
-	0xb8, 0x2f, 0x8c, 0x67, 0x12, 0xa9, 0xe7, 0x7e, 0x8b, 0xdc, 0xd9, 0x03, 0x07, 0x23, 0x17, 0x2a,
-	0xaa, 0x44, 0xea, 0x41, 0xdc, 0x22, 0x77, 0x06, 0xf3, 0x60, 0x64, 0xaa, 0xa2, 0x24, 0x32, 0x80,
-	0x8a, 0x1a, 0x55, 0x72, 0xb9, 0x0d, 0xdd, 0x4e, 0xee, 0x1e, 0xe0, 0x13, 0x05, 0x7c, 0xe4, 0x93,
-	0x1d, 0x60, 0x21, 0x83, 0x24, 0x2f, 0x01, 0x67, 0x53, 0x5c, 0xe2, 0xad, 0xa3, 0xef, 0x4f, 0x77,
-	0xf3, 0x7a, 0x8f, 0xa5, 0xbc, 0xe0, 0xa9, 0xba, 0xe0, 0x6d, 0xff, 0xad, 0x9d, 0x0b, 0x66, 0xc8,
-	0x74, 0x63, 0xbc, 0x30, 0x9e, 0x4d, 0x6c, 0xf5, 0xf7, 0xfb, 0xf4, 0xef, 0x00, 0x00, 0x00, 0xff,
-	0xff, 0x08, 0xba, 0x29, 0x2a, 0x2d, 0x07, 0x00, 0x00,
+	0x14, 0x80, 0xeb, 0xc4, 0x71, 0xe3, 0x93, 0xb4, 0x75, 0xa7, 0x2d, 0xeb, 0x86, 0x5d, 0xc8, 0x1a,
+	0x01, 0xd1, 0x22, 0x25, 0x50, 0xf6, 0x02, 0xad, 0x10, 0x52, 0xd4, 0x85, 0x50, 0x09, 0x9c, 0xc5,
+	0xd9, 0x55, 0x2f, 0x2d, 0xc7, 0x3e, 0x09, 0x23, 0xa5, 0x63, 0x33, 0x33, 0x49, 0xe0, 0x16, 0x89,
+	0x27, 0x80, 0x0b, 0x5e, 0x84, 0x27, 0x41, 0xe2, 0x09, 0x78, 0x10, 0x34, 0x33, 0x4e, 0x42, 0x4a,
+	0x16, 0xe5, 0x62, 0xef, 0xe6, 0xfc, 0x7d, 0x73, 0x3c, 0xe7, 0xc7, 0x00, 0x73, 0x81, 0xbc, 0x5b,
+	0xf0, 0x5c, 0xe6, 0xa4, 0x52, 0x8c, 0x5b, 0x0f, 0xa7, 0x79, 0x3e, 0x9d, 0x61, 0x2f, 0x29, 0x68,
+	0x2f, 0x61, 0x2c, 0x97, 0x89, 0xa4, 0x39, 0x13, 0xc6, 0x23, 0x38, 0x85, 0x93, 0x57, 0x02, 0xf9,
+	0x37, 0x54, 0xc8, 0x08, 0x7f, 0x98, 0xa3, 0x90, 0xc1, 0x6f, 0x16, 0x9c, 0x2a, 0xdd, 0x35, 0xc7,
+	0x44, 0x62, 0xa9, 0x25, 0x2d, 0xa8, 0x2b, 0x30, 0x4b, 0xee, 0xd0, 0xb7, 0xda, 0x56, 0xc7, 0x8d,
+	0xd6, 0xb2, 0xb2, 0x15, 0x89, 0x10, 0xcb, 0x9c, 0x67, 0x7e, 0xc5, 0xd8, 0x56, 0x32, 0x39, 0x83,
+	0x1a, 0xcb, 0xe3, 0xe9, 0xd2, 0xaf, 0xb6, 0xad, 0x4e, 0x3d, 0xb2, 0x59, 0x3e, 0x58, 0x92, 0x07,
+	0x70, 0xf8, 0x7d, 0x2e, 0x64, 0x4c, 0x33, 0xdf, 0x6e, 0x5b, 0x9d, 0xa3, 0xc8, 0x51, 0xe2, 0x4d,
+	0x46, 0x2e, 0xa1, 0x4e, 0x45, 0x9c, 0x64, 0x77, 0x94, 0xf9, 0x35, 0x1d, 0x70, 0x48, 0x45, 0x5f,
+	0x89, 0xc1, 0x1f, 0x55, 0x93, 0xd6, 0xab, 0x22, 0x7b, 0x03, 0x69, 0x3d, 0x05, 0x67, 0xba, 0x2c,
+	0x38, 0x4e, 0x74, 0x5e, 0xc7, 0x57, 0x0f, 0xbb, 0xc5, 0xb8, 0xfb, 0x1f, 0x7c, 0x77, 0x70, 0xfb,
+	0x82, 0xe3, 0x24, 0x2a, 0x7d, 0x5f, 0x9f, 0x77, 0x1f, 0x1a, 0x42, 0x3d, 0x6c, 0x1a, 0x6b, 0x66,
+	0x4d, 0x33, 0xdb, 0xbb, 0x99, 0x23, 0xed, 0xa8, 0xb9, 0x20, 0xd6, 0x67, 0xf2, 0x05, 0x80, 0xfe,
+	0x6e, 0x43, 0x70, 0x34, 0xe1, 0xdd, 0xdd, 0x04, 0xfd, 0x20, 0x1a, 0xe0, 0x26, 0xab, 0x63, 0xf0,
+	0x01, 0x38, 0x26, 0x5b, 0x02, 0xe0, 0x84, 0xc3, 0x17, 0xd1, 0x97, 0x5f, 0x79, 0x07, 0xa4, 0x0e,
+	0x76, 0x38, 0x1c, 0xdc, 0x7a, 0x16, 0x71, 0xa0, 0x32, 0xb8, 0xf5, 0x2a, 0xc1, 0x67, 0x00, 0x9b,
+	0x0c, 0x88, 0x07, 0x4d, 0xe3, 0x3b, 0x7a, 0xd9, 0x7f, 0x79, 0x73, 0xed, 0x1d, 0x90, 0x26, 0xd4,
+	0xc3, 0x61, 0x29, 0x59, 0x8a, 0x55, 0x9e, 0x2b, 0xc1, 0x53, 0x70, 0xd7, 0x37, 0x93, 0x13, 0x68,
+	0x98, 0xc0, 0xfe, 0xf3, 0x6f, 0x6f, 0x42, 0xef, 0x80, 0x34, 0xe0, 0x30, 0x1c, 0x1a, 0xc1, 0x22,
+	0x2e, 0xd4, 0xcc, 0xb1, 0x12, 0xf4, 0x4c, 0xd9, 0x9e, 0xe3, 0x0c, 0xf7, 0x2a, 0x5b, 0xd0, 0x05,
+	0x4f, 0x05, 0x44, 0xc8, 0x70, 0xb9, 0x8f, 0xff, 0x15, 0x9c, 0x2b, 0xff, 0x01, 0xb2, 0xeb, 0x9c,
+	0x4d, 0xe8, 0x74, 0x9f, 0x98, 0xbf, 0xaa, 0xd0, 0x34, 0x97, 0x88, 0x22, 0x67, 0x02, 0xc9, 0x47,
+	0x50, 0x53, 0x46, 0xe1, 0x5b, 0xed, 0x6a, 0xa7, 0x71, 0x75, 0xb1, 0x7a, 0xf8, 0x95, 0x83, 0x11,
+	0x8c, 0x4f, 0xeb, 0xf7, 0x2a, 0xd8, 0x4a, 0xfe, 0xdf, 0xee, 0xfb, 0x18, 0xce, 0x05, 0xf2, 0x05,
+	0xf2, 0x58, 0x20, 0xa7, 0xc9, 0x2c, 0x66, 0xf3, 0xbb, 0x31, 0xf2, 0xb2, 0x13, 0x89, 0xb1, 0x8d,
+	0xb4, 0x29, 0xd4, 0x16, 0x42, 0xc0, 0x4e, 0x91, 0x4b, 0xdd, 0x91, 0x6e, 0xa4, 0xcf, 0xe4, 0x11,
+	0x40, 0xaa, 0xe7, 0x30, 0x8b, 0x13, 0xa9, 0x9b, 0xce, 0x8d, 0xdc, 0x52, 0xd3, 0x97, 0xe4, 0x02,
+	0x1c, 0x5a, 0xc4, 0x0c, 0xa5, 0x6e, 0x39, 0x37, 0xaa, 0xd1, 0x22, 0x44, 0xb9, 0x19, 0x3a, 0x67,
+	0xf7, 0xd0, 0x1d, 0xbe, 0x76, 0xe8, 0xea, 0x5b, 0x43, 0x47, 0x1e, 0x43, 0x93, 0x8a, 0x38, 0xcd,
+	0x19, 0xc3, 0x54, 0x62, 0xe6, 0xbb, 0xda, 0xdc, 0xa0, 0xe2, 0x7a, 0xa5, 0x22, 0x1f, 0xc2, 0xc9,
+	0xda, 0x1e, 0x0b, 0xca, 0x52, 0xf4, 0x41, 0xe7, 0x72, 0xbc, 0x56, 0x8f, 0x94, 0x56, 0x7d, 0xca,
+	0xf8, 0x27, 0x89, 0x22, 0x16, 0xc8, 0xa4, 0xdf, 0x68, 0x5b, 0x1d, 0x3b, 0x72, 0xb5, 0x66, 0x84,
+	0x4c, 0x92, 0xf7, 0xe1, 0xd8, 0x98, 0x39, 0xa6, 0x48, 0x17, 0x98, 0xf9, 0x4d, 0xed, 0x72, 0xa4,
+	0xb5, 0x51, 0xa9, 0x54, 0x14, 0xfc, 0xb1, 0xa0, 0x1c, 0x85, 0x7a, 0x90, 0x23, 0xf3, 0x20, 0xa5,
+	0xa6, 0x2f, 0x83, 0xcf, 0xe1, 0xe2, 0x5e, 0x33, 0x94, 0x05, 0x7e, 0x0f, 0x8e, 0xd2, 0x19, 0x45,
+	0x26, 0xd5, 0xd7, 0x4c, 0xe8, 0xb4, 0xac, 0x57, 0xd3, 0x28, 0x8d, 0xf3, 0xd5, 0x2f, 0x36, 0x34,
+	0x54, 0xf8, 0x08, 0xf9, 0x82, 0xa6, 0x48, 0xbe, 0x06, 0x5b, 0x6d, 0x46, 0x72, 0xb6, 0x6a, 0x87,
+	0x7f, 0xed, 0xc9, 0x96, 0x77, 0xbf, 0x47, 0x82, 0xcb, 0x9f, 0xff, 0xfc, 0xfb, 0xd7, 0xca, 0x19,
+	0x39, 0xd5, 0xcb, 0x76, 0xf1, 0x49, 0x4f, 0x35, 0x43, 0x6f, 0xa6, 0x08, 0xdf, 0x81, 0x63, 0xf6,
+	0x29, 0x59, 0xb7, 0xd6, 0xd6, 0x7e, 0xdd, 0x41, 0x7b, 0x47, 0xd3, 0xfc, 0xe0, 0x6c, 0x8b, 0x66,
+	0x6a, 0xff, 0xcc, 0x7a, 0xa2, 0x90, 0x66, 0x2d, 0x6c, 0x90, 0x5b, 0x6b, 0x62, 0x6f, 0xe4, 0x5c,
+	0x47, 0x95, 0x48, 0x33, 0xa7, 0x1b, 0xe4, 0xd6, 0xdc, 0xee, 0x8d, 0xcc, 0x74, 0x94, 0x42, 0x86,
+	0x50, 0xd3, 0x93, 0x4c, 0xce, 0x37, 0xa1, 0x9b, 0xc1, 0xde, 0x01, 0x7c, 0xa4, 0x81, 0x0f, 0x02,
+	0xb2, 0x05, 0xe4, 0x2a, 0x48, 0xf1, 0x52, 0x70, 0xd7, 0xc5, 0x25, 0xfe, 0x2a, 0xfa, 0xfe, 0xf0,
+	0xb7, 0x2e, 0x77, 0x58, 0xca, 0x0b, 0x1e, 0xeb, 0x0b, 0xde, 0x0e, 0xde, 0xda, 0xba, 0x60, 0x8a,
+	0xcc, 0x34, 0xc6, 0x33, 0xeb, 0xc9, 0xd8, 0xd1, 0x3f, 0xc7, 0x4f, 0xff, 0x09, 0x00, 0x00, 0xff,
+	0xff, 0x42, 0xdb, 0x7d, 0x5f, 0x4c, 0x07, 0x00, 0x00,
 }

+ 1 - 0
api/pb/user.proto

@@ -110,6 +110,7 @@ message UserResponse {
     string connected_since = 10;
     uint64 bytes_sent = 11;
     uint64 bytes_received = 12;
+    string expires_at = 13;
   }
 
   repeated User users = 1;

+ 53 - 35
api/pb/vpn.pb.go

@@ -142,6 +142,8 @@ type VPNStatusResponse struct {
 	CreatedAt    string `protobuf:"bytes,9,opt,name=created_at,json=createdAt" json:"created_at,omitempty"`
 	Proto        string `protobuf:"bytes,10,opt,name=proto" json:"proto,omitempty"`
 	Dns          string `protobuf:"bytes,11,opt,name=dns" json:"dns,omitempty"`
+	ExpiresAt    string `protobuf:"bytes,12,opt,name=expires_at,json=expiresAt" json:"expires_at,omitempty"`
+	CaExpiresAt  string `protobuf:"bytes,13,opt,name=ca_expires_at,json=caExpiresAt" json:"ca_expires_at,omitempty"`
 }
 
 func (m *VPNStatusResponse) Reset()                    { *m = VPNStatusResponse{} }
@@ -226,6 +228,20 @@ func (m *VPNStatusResponse) GetDns() string {
 	return ""
 }
 
+func (m *VPNStatusResponse) GetExpiresAt() string {
+	if m != nil {
+		return m.ExpiresAt
+	}
+	return ""
+}
+
+func (m *VPNStatusResponse) GetCaExpiresAt() string {
+	if m != nil {
+		return m.CaExpiresAt
+	}
+	return ""
+}
+
 type VPNInitResponse struct {
 }
 
@@ -436,39 +452,41 @@ var _VPNService_serviceDesc = grpc.ServiceDesc{
 func init() { proto.RegisterFile("vpn.proto", fileDescriptor1) }
 
 var fileDescriptor1 = []byte{
-	// 537 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x6e, 0xd3, 0x40,
-	0x10, 0x86, 0xb1, 0x93, 0x3a, 0xc9, 0x50, 0x8a, 0x3b, 0x4d, 0xa9, 0x31, 0x54, 0xaa, 0xcc, 0xa5,
-	0x2a, 0x52, 0x22, 0xca, 0x8d, 0x0b, 0x82, 0x02, 0x12, 0x12, 0x32, 0x26, 0x34, 0xb9, 0x46, 0x1b,
-	0x67, 0x5b, 0xac, 0x26, 0xeb, 0xc5, 0xbb, 0xc9, 0x03, 0xf0, 0x0a, 0x48, 0x1c, 0x78, 0x2d, 0x6e,
-	0x9c, 0x79, 0x10, 0xe4, 0xd9, 0x75, 0x6a, 0x47, 0x70, 0x9b, 0xfd, 0x67, 0xe7, 0xd3, 0xcc, 0x3f,
-	0x03, 0xbd, 0xb5, 0x14, 0x03, 0x59, 0xe4, 0x3a, 0x47, 0x57, 0xce, 0xc2, 0xc7, 0xd7, 0x79, 0x7e,
-	0xbd, 0xe0, 0x43, 0x26, 0xb3, 0x21, 0x13, 0x22, 0xd7, 0x4c, 0x67, 0xb9, 0x50, 0xe6, 0x47, 0x84,
-	0xe0, 0x4f, 0x92, 0xf8, 0xb3, 0x66, 0x7a, 0xa5, 0x46, 0xfc, 0xeb, 0x8a, 0x2b, 0x1d, 0xfd, 0x74,
-	0x60, 0x6f, 0x92, 0xc4, 0xef, 0x45, 0xa6, 0xad, 0x84, 0x21, 0x74, 0xbf, 0xe4, 0x4a, 0x0b, 0xb6,
-	0xe4, 0x81, 0x73, 0xe2, 0x9c, 0xf6, 0x46, 0x9b, 0x37, 0x22, 0xb4, 0x65, 0x5e, 0xe8, 0xc0, 0x25,
-	0x9d, 0x62, 0x7c, 0x0a, 0x40, 0xfc, 0xa9, 0x2c, 0xf8, 0x55, 0xd0, 0x3a, 0x71, 0x4e, 0xf7, 0xce,
-	0x77, 0x07, 0x72, 0x36, 0x98, 0x24, 0x71, 0x52, 0x26, 0x46, 0x3d, 0xca, 0x27, 0x05, 0xbf, 0xc2,
-	0x87, 0xd0, 0xcd, 0xe4, 0x74, 0xb6, 0xc8, 0xd3, 0x9b, 0xa0, 0x4d, 0x90, 0x4e, 0x26, 0x5f, 0x97,
-	0x4f, 0xf4, 0xa1, 0x35, 0x17, 0x2a, 0xd8, 0x21, 0xb5, 0x0c, 0xa3, 0x97, 0xd4, 0xf0, 0x58, 0xce,
-	0x99, 0xe6, 0x55, 0x77, 0x75, 0x80, 0xf3, 0x4f, 0x80, 0x7b, 0x0b, 0x38, 0x80, 0xfd, 0x49, 0x12,
-	0x8f, 0xb8, 0xd2, 0xac, 0xa8, 0xe6, 0x8b, 0x7e, 0xb8, 0xa4, 0x56, 0x3e, 0x28, 0x99, 0x0b, 0x45,
-	0x93, 0xd5, 0x26, 0xa6, 0x18, 0x9f, 0xc0, 0x3d, 0xc5, 0x8b, 0x8c, 0x2d, 0xa6, 0x62, 0xb5, 0x9c,
-	0xf1, 0xc2, 0xa2, 0x77, 0x8d, 0x18, 0x93, 0xd6, 0xb0, 0xab, 0xf5, 0x1f, 0xbb, 0xda, 0x35, 0xbb,
-	0x10, 0xda, 0x29, 0x2f, 0xb4, 0x9d, 0x93, 0x62, 0x3c, 0x82, 0x4e, 0xca, 0xa6, 0x24, 0x7b, 0x24,
-	0x7b, 0x29, 0xbb, 0x28, 0x13, 0x3e, 0xb4, 0x04, 0xd7, 0x41, 0xc7, 0x8c, 0x24, 0x38, 0x95, 0x2f,
-	0x99, 0xba, 0x09, 0xba, 0xa6, 0xbc, 0x8c, 0xf1, 0x18, 0x20, 0x2d, 0x38, 0xd3, 0x7c, 0x3e, 0x65,
-	0x3a, 0xe8, 0x51, 0xa6, 0x67, 0x95, 0x57, 0x1a, 0xfb, 0xb0, 0x43, 0x0b, 0x08, 0x80, 0x32, 0xe6,
-	0x51, 0xb9, 0x75, 0xf7, 0xd6, 0xad, 0x7d, 0xb8, 0xbf, 0x39, 0x05, 0xe3, 0x8a, 0x35, 0xb0, 0xda,
-	0x80, 0x15, 0xfb, 0x80, 0x75, 0x57, 0x8d, 0x7a, 0x76, 0x0a, 0xdd, 0x6a, 0xe1, 0x08, 0xe0, 0xc5,
-	0x1f, 0x93, 0xd1, 0xdb, 0x77, 0xfe, 0x1d, 0xec, 0x40, 0x6b, 0xfc, 0x26, 0xf1, 0x9d, 0x32, 0xb8,
-	0xbc, 0x48, 0x7c, 0xf7, 0xfc, 0xb7, 0x0b, 0x50, 0x2e, 0x80, 0x17, 0xeb, 0x2c, 0xe5, 0xf8, 0x09,
-	0x3c, 0xb3, 0x0b, 0xec, 0xdb, 0xab, 0x69, 0x9c, 0x68, 0x78, 0xb8, 0xa5, 0xda, 0x2e, 0xc2, 0x6f,
-	0xbf, 0xfe, 0x7c, 0x77, 0xfb, 0x88, 0x74, 0xed, 0xeb, 0x67, 0xc3, 0xb5, 0x14, 0x43, 0x65, 0x40,
-	0x1f, 0xa0, 0x5d, 0x8e, 0x81, 0x68, 0x4b, 0x6b, 0xe7, 0x1d, 0x1e, 0x34, 0x34, 0x0b, 0x7b, 0x44,
-	0xb0, 0xc3, 0xc8, 0xaf, 0xc3, 0x32, 0x91, 0xe9, 0x17, 0xce, 0x19, 0x5e, 0x82, 0x67, 0x1c, 0xd8,
-	0x34, 0xd8, 0x38, 0xc9, 0x4d, 0x83, 0x5b, 0x36, 0x1d, 0x13, 0xf3, 0x28, 0x6a, 0x34, 0xb8, 0xa2,
-	0x3f, 0x25, 0x75, 0x0c, 0x1d, 0x6b, 0x21, 0x56, 0x80, 0xe6, 0xa1, 0x86, 0x0f, 0xb6, 0xe5, 0xad,
-	0x66, 0x0f, 0xea, 0xe0, 0xc2, 0x7c, 0x9a, 0x79, 0xb4, 0xdd, 0xe7, 0x7f, 0x03, 0x00, 0x00, 0xff,
-	0xff, 0x04, 0xc8, 0xb8, 0x7c, 0x1a, 0x04, 0x00, 0x00,
+	// 568 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x93, 0xcd, 0x6e, 0xd3, 0x40,
+	0x10, 0xc7, 0xb1, 0x93, 0xe6, 0x63, 0xfa, 0x81, 0x3b, 0x4d, 0xa9, 0x09, 0x54, 0xaa, 0xcc, 0xa5,
+	0x2a, 0x52, 0x23, 0xca, 0x8d, 0x0b, 0x2a, 0xa5, 0x48, 0x48, 0xc8, 0x98, 0xd0, 0xe6, 0x6a, 0x6d,
+	0xdc, 0x6d, 0xb1, 0xda, 0xac, 0x97, 0xdd, 0x4d, 0xc4, 0x99, 0x57, 0xe0, 0xc6, 0x6b, 0x71, 0x82,
+	0x33, 0x0f, 0x82, 0x3c, 0xbb, 0x0e, 0x76, 0x04, 0xb7, 0xf1, 0x7f, 0x66, 0x7f, 0x9a, 0xf9, 0xcf,
+	0x18, 0xfa, 0x0b, 0x29, 0x8e, 0xa5, 0x2a, 0x4c, 0x81, 0xbe, 0x9c, 0x0e, 0x1f, 0xdf, 0x14, 0xc5,
+	0xcd, 0x1d, 0x1f, 0x31, 0x99, 0x8f, 0x98, 0x10, 0x85, 0x61, 0x26, 0x2f, 0x84, 0xb6, 0x15, 0x11,
+	0x42, 0x30, 0x49, 0xe2, 0x8f, 0x86, 0x99, 0xb9, 0x1e, 0xf3, 0xcf, 0x73, 0xae, 0x4d, 0xf4, 0xdd,
+	0x83, 0xad, 0x49, 0x12, 0xbf, 0x15, 0xb9, 0x71, 0x12, 0x0e, 0xa1, 0xf7, 0xa9, 0xd0, 0x46, 0xb0,
+	0x19, 0x0f, 0xbd, 0x03, 0xef, 0xb0, 0x3f, 0x5e, 0x7e, 0x23, 0x42, 0x5b, 0x16, 0xca, 0x84, 0x3e,
+	0xe9, 0x14, 0xe3, 0x53, 0x00, 0xe2, 0xa7, 0x52, 0xf1, 0xeb, 0xb0, 0x75, 0xe0, 0x1d, 0x6e, 0x9d,
+	0x6c, 0x1c, 0xcb, 0xe9, 0xf1, 0x24, 0x89, 0x93, 0x32, 0x31, 0xee, 0x53, 0x3e, 0x51, 0xfc, 0x1a,
+	0x1f, 0x42, 0x2f, 0x97, 0xe9, 0xf4, 0xae, 0xc8, 0x6e, 0xc3, 0x36, 0x41, 0xba, 0xb9, 0x7c, 0x55,
+	0x7e, 0x62, 0x00, 0xad, 0x2b, 0xa1, 0xc3, 0x35, 0x52, 0xcb, 0x30, 0x7a, 0x49, 0x0d, 0x5f, 0xca,
+	0x2b, 0x66, 0x78, 0xd5, 0x5d, 0x1d, 0xe0, 0xfd, 0x13, 0xe0, 0xff, 0x05, 0xec, 0xc0, 0xf6, 0x24,
+	0x89, 0xc7, 0x5c, 0x1b, 0xa6, 0xaa, 0xf9, 0xa2, 0x9f, 0x3e, 0xa9, 0x95, 0x0f, 0x5a, 0x16, 0x42,
+	0xd3, 0x64, 0xb5, 0x89, 0x29, 0xc6, 0x27, 0xb0, 0xa9, 0xb9, 0xca, 0xd9, 0x5d, 0x2a, 0xe6, 0xb3,
+	0x29, 0x57, 0x0e, 0xbd, 0x61, 0xc5, 0x98, 0xb4, 0x86, 0x5d, 0xad, 0xff, 0xd8, 0xd5, 0xae, 0xd9,
+	0x85, 0xd0, 0xce, 0xb8, 0x32, 0x6e, 0x4e, 0x8a, 0x71, 0x0f, 0xba, 0x19, 0x4b, 0x49, 0xee, 0x90,
+	0xdc, 0xc9, 0xd8, 0x59, 0x99, 0x08, 0xa0, 0x25, 0xb8, 0x09, 0xbb, 0x76, 0x24, 0xc1, 0xe9, 0xf9,
+	0x8c, 0xe9, 0xdb, 0xb0, 0x67, 0x9f, 0x97, 0x31, 0xee, 0x03, 0x64, 0x8a, 0x33, 0xc3, 0xaf, 0x52,
+	0x66, 0xc2, 0x3e, 0x65, 0xfa, 0x4e, 0x39, 0x35, 0x38, 0x80, 0x35, 0x5a, 0x40, 0x08, 0x94, 0xb1,
+	0x1f, 0x95, 0x5b, 0xeb, 0x4b, 0xb7, 0x4a, 0x0c, 0xff, 0x22, 0x73, 0xc5, 0x75, 0x89, 0xd9, 0xb0,
+	0x18, 0xa7, 0x9c, 0x1a, 0x8c, 0x60, 0x33, 0x63, 0x69, 0xad, 0x62, 0x93, 0x2a, 0xd6, 0x33, 0x76,
+	0x5e, 0xd5, 0x44, 0xdb, 0x70, 0x7f, 0x79, 0x4d, 0xd6, 0x58, 0xb7, 0x83, 0x6a, 0x89, 0x4e, 0x1c,
+	0x00, 0xd6, 0x17, 0x63, 0xd5, 0xa3, 0x43, 0xe8, 0x55, 0x37, 0x83, 0x00, 0x9d, 0xf8, 0x7d, 0x32,
+	0x3e, 0x7f, 0x13, 0xdc, 0xc3, 0x2e, 0xb4, 0x2e, 0x5f, 0x27, 0x81, 0x57, 0x06, 0x17, 0x67, 0x49,
+	0xe0, 0x9f, 0xfc, 0xf2, 0x01, 0xca, 0x1d, 0x72, 0xb5, 0xc8, 0x33, 0x8e, 0x1f, 0xa0, 0x63, 0xd7,
+	0x89, 0x03, 0x77, 0x78, 0x8d, 0x2b, 0x1f, 0xee, 0xae, 0xa8, 0xae, 0x8b, 0xe1, 0xd7, 0x1f, 0xbf,
+	0xbf, 0xf9, 0x03, 0x44, 0xfa, 0x61, 0x16, 0xcf, 0x46, 0x0b, 0x29, 0x46, 0xda, 0x82, 0xde, 0x41,
+	0xbb, 0x1c, 0x03, 0xd1, 0x3d, 0xad, 0xfd, 0x21, 0xc3, 0x9d, 0x86, 0xe6, 0x60, 0x8f, 0x08, 0xb6,
+	0x1b, 0x05, 0x75, 0x58, 0x2e, 0x72, 0xf3, 0xc2, 0x3b, 0xc2, 0x0b, 0xe8, 0x58, 0x07, 0x96, 0x0d,
+	0x36, 0xae, 0x7a, 0xd9, 0xe0, 0x8a, 0x4d, 0xfb, 0xc4, 0xdc, 0x8b, 0x1a, 0x0d, 0xce, 0xa9, 0xa6,
+	0xa4, 0x5e, 0x42, 0xd7, 0x59, 0x88, 0x15, 0xa0, 0x79, 0xeb, 0xc3, 0x07, 0xab, 0xf2, 0x4a, 0xb3,
+	0x3b, 0x75, 0xb0, 0xb2, 0x45, 0xd3, 0x0e, 0x1d, 0xc8, 0xf3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff,
+	0xd4, 0x74, 0x98, 0x4b, 0x5d, 0x04, 0x00, 0x00,
 }

+ 2 - 0
api/pb/vpn.proto

@@ -63,6 +63,8 @@ message VPNStatusResponse {
   string created_at = 9;
   string proto = 10;
   string dns = 11;
+  string expires_at = 12;
+  string ca_expires_at = 13;
 }
 message VPNInitResponse {}
 message VPNUpdateResponse {}

+ 4 - 1
api/rpc.go

@@ -100,6 +100,7 @@ func (s *UserService) List(ctx context.Context, req *pb.UserListRequest) (*pb.Us
 			ConnectedSince:     connectedSince.UTC().Format(time.RFC3339),
 			BytesSent:          bytesSent,
 			BytesReceived:      bytesReceived,
+			ExpiresAt:          user.ExpiresAt().UTC().Format(time.RFC3339),
 		})
 	}
 
@@ -341,12 +342,14 @@ func (s *VPNService) Status(ctx context.Context, req *pb.VPNStatusRequest) (*pb.
 		Hostname:     server.GetHostname(),
 		Port:         server.GetPort(),
 		Proto:        server.GetProto(),
-		Cert:         server.GetCert(),
+		Cert:         server.Cert,
 		CaCert:       server.GetCACert(),
 		Net:          server.GetNet(),
 		Mask:         server.GetMask(),
 		CreatedAt:    server.GetCreatedAt(),
 		Dns:          server.GetDNS(),
+		ExpiresAt:    server.ExpiresAt().UTC().Format(time.RFC3339),
+		CaExpiresAt:  server.CAExpiresAt().UTC().Format(time.RFC3339),
 	}
 	return &response, nil
 }

Diferenças do arquivo suprimidas por serem muito extensas
+ 4 - 0
bindata/bindata.go


+ 11 - 3
cmd/ovpm/action_user.go

@@ -54,12 +54,11 @@ func userListAction(rpcServURLStr string) error {
 	}
 
 	// Prepare table data.
-	header := []string{"#", "username", "ip", "created", "crt", "push gw", "admin"}
+	header := []string{"#", "username", "ip", "created", "crt exp", "push gw", "admin"}
 	rows := [][]string{}
 	for i, user := range userListResp.Users {
 		isConnected := " "
 		if user.IsConnected {
-			//isConnected = fmt.Sprintf("%s●%s", "\x1b[32m", "\x1b[0m\x1b[0m") // green ascii dot
 			isConnected = fmt.Sprintf("%s●%s", "", "") // colorless ascii dot
 		}
 		static := ""
@@ -73,7 +72,16 @@ func userListAction(rpcServURLStr string) error {
 
 		isValidCRT := "✘"
 		if user.ServerSerialNumber == vpnStatusResp.SerialNumber {
-			isValidCRT = "✔"
+			expiresAt, err := time.Parse(time.RFC3339, user.ExpiresAt)
+			if err != nil {
+				exit(1)
+				return errors.UnknownSysError(err)
+			}
+
+			// Check if the cert is expired.
+			if expiresAt.After(time.Now()) {
+				isValidCRT = fmt.Sprintf("in %s", humanize.Time(expiresAt))
+			}
 		}
 
 		isPushGW := "✘"

+ 2 - 0
cmd/ovpm/action_vpn.go

@@ -50,6 +50,8 @@ func vpnStatusAction(rpcServURLStr string) error {
 	table.Append([]string{"Netmask", vpnStatusResp.Mask})
 	table.Append([]string{"Created At", vpnStatusResp.CreatedAt})
 	table.Append([]string{"DNS", vpnStatusResp.Dns})
+	table.Append([]string{"Cert Exp", vpnStatusResp.ExpiresAt})
+	table.Append([]string{"CA Cert Exp", vpnStatusResp.CaExpiresAt})
 	table.Render()
 
 	return nil

+ 3 - 0
template/auth.swagger.json

@@ -103,6 +103,9 @@
         "bytes_received": {
           "type": "string",
           "format": "uint64"
+        },
+        "expires_at": {
+          "type": "string"
         }
       }
     },

Diferenças do arquivo suprimidas por serem muito extensas
+ 4 - 0
template/bootstrap.min.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
template/bundle.js


BIN
template/glyphicons-halflings-regular.woff


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
template/mui.min.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
template/mui.min.js


+ 3 - 0
template/user.swagger.json

@@ -207,6 +207,9 @@
         "bytes_received": {
           "type": "string",
           "format": "uint64"
+        },
+        "expires_at": {
+          "type": "string"
         }
       }
     },

+ 6 - 0
template/vpn.swagger.json

@@ -171,6 +171,12 @@
         },
         "dns": {
           "type": "string"
+        },
+        "expires_at": {
+          "type": "string"
+        },
+        "ca_expires_at": {
+          "type": "string"
         }
       }
     },

+ 22 - 3
vpn.go

@@ -127,9 +127,28 @@ func (svr *Server) GetProto() string {
 	return DefaultVPNProto
 }
 
-// GetCert returns vpn server's cert.
-func (svr *Server) GetCert() string {
-	return svr.Cert
+// CAExpiresAt returns the expiry date time of the CA.
+func (svr *Server) CAExpiresAt() time.Time {
+	if !svr.IsInitialized() {
+		return time.Time{}
+	}
+	crt, err := pki.ReadCertFromPEM(svr.CACert)
+	if err != nil {
+		logrus.Fatalf("can't parse cert: %v", err)
+	}
+	return crt.NotAfter
+}
+
+// ExpiresAt returns the expiry date time of the server cert.
+func (svr *Server) ExpiresAt() time.Time {
+	if !svr.IsInitialized() {
+		return time.Time{}
+	}
+	crt, err := pki.ReadCertFromPEM(svr.Cert)
+	if err != nil {
+		logrus.Fatalf("can't parse cert: %v", err)
+	}
+	return crt.NotAfter
 }
 
 // GetKey returns vpn server's key.

+ 37 - 0
vpn_test.go

@@ -2,11 +2,13 @@ package ovpm
 
 import (
 	"io"
+	"reflect"
 	"strings"
 	"testing"
 	"time"
 
 	"github.com/Sirupsen/logrus"
+	"github.com/cad/ovpm/pki"
 	"github.com/cad/ovpm/supervisor"
 )
 
@@ -554,6 +556,41 @@ func TestGetConnectedUsers(t *testing.T) {
 	}
 }
 
+func TestVPN_ExpiresAt(t *testing.T) {
+	// Initialize:
+	db := CreateDB("sqlite3", ":memory:")
+	defer db.Cease()
+	svr := TheServer()
+	svr.Init("localhost", "", UDPProto, "", "")
+
+	// Test:
+	cert, err := pki.ReadCertFromPEM(svr.Cert)
+	if err != nil {
+		t.Fatalf("test preperation failed: %v", err)
+	}
+
+	if !reflect.DeepEqual(svr.ExpiresAt(), cert.NotAfter) {
+		t.Errorf("got (%s), want (%s)", svr.ExpiresAt(), cert.NotAfter)
+	}
+}
+
+func TestVPN_CAExpiresAt(t *testing.T) {
+	// Initialize:
+	db := CreateDB("sqlite3", ":memory:")
+	defer db.Cease()
+	svr := TheServer()
+	svr.Init("localhost", "", UDPProto, "", "")
+
+	// Test:
+	cert, err := pki.ReadCertFromPEM(svr.CACert)
+	if err != nil {
+		t.Fatalf("test preperation failed: %v", err)
+	}
+	if !reflect.DeepEqual(svr.CAExpiresAt(), cert.NotAfter) {
+		t.Errorf("got (%s), want (%s)", svr.CAExpiresAt(), cert.NotAfter)
+	}
+}
+
 func init() {
 	// Init
 	Testing = true

+ 10 - 0
webui/ovpm/app/components/Dashboard/AdminDashboard/index.jsx

@@ -458,6 +458,12 @@ export default class AdminDashboard extends React.Component {
                 isOnline = (<span className="text-success" style={{"font-size":"2em", "vertical-align": "middle"}} data-toggle="tooltip" title={onlineSince}>•</span>)
             }
 
+            let certExpiry = (<span className="glyphicon glyphicon-remove" data-toggle="tooltip" title="Expired"></span>)
+            if (moment(this.state.users[i].expires_at).isAfter(moment.now())) {
+                let expiresIn = "expires " + moment(this.state.users[i].expires_at).fromNow()
+                certExpiry = (<span data-toggle="tooltip" title={this.state.users[i].expires_at}>{expiresIn}</span>)
+            }
+
             let createdAt = (<span data-toggle="tooltip" title={this.state.users[i].created_at}>{moment(this.state.users[i].created_at).fromNow()}</span>)
 
             users.push(
@@ -466,6 +472,7 @@ export default class AdminDashboard extends React.Component {
                     <td>{isOnline} {this.state.users[i].username} {isAdmin}</td>
                     <td>{this.state.users[i].ip_net} {isStatic}</td>
                     <td>{createdAt}</td>
+                    <td>{certExpiry}</td>
                     <td className="mui--align-middle">{noGW}</td>
                     <td>
                         <a style={{"padding-left": "5px"}}><span className="glyphicon glyphicon-floppy-save" data-toggle="tooltip" title="Download VPN Profile" onClick={this.handleDownloadProfileClick.bind(this, this.state.users[i].username)}></span></a>
@@ -537,6 +544,7 @@ export default class AdminDashboard extends React.Component {
                                                 <th>USERNAME</th>
                                                 <th>IP</th>
                                                 <th>CREATED AT</th>
+                                                <th>CERT</th>
                                                 <th>PUSH GATEWAY</th>
                                                 <th>ACTIONS</th>
                                             </tr>
@@ -581,6 +589,8 @@ export default class AdminDashboard extends React.Component {
                                             <tr><td>Network</td>   <td>{this.state.vpn.net} ({this.state.vpn.mask})</td></tr>
                                             <tr><td>DNS</td>       <td>{this.state.vpn.dns}</td></tr>
                                             <tr><td>Created At</td><td>{this.state.vpn.created_at}</td></tr>
+                                            <tr><td>Expires At</td><td>{this.state.vpn.expires_at}</td></tr>
+                                            <tr><td>CA Expires At</td><td>{this.state.vpn.ca_expires_at}</td></tr>
                                         </tbody>
                                     </table>
                                 </Tab>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
webui/ovpm/public/bundle.js


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff