--- /dev/null
+package api
+
+import (
+ "fmt"
+
+ "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db"
+)
+
+type GetAllPortfoliosQuery struct {
+ In struct {
+ Market string
+ }
+ Out map[string]Portfolio
+}
+
+func (q GetAllPortfoliosQuery) ValidateParams() *Error {
+ if q.In.Market != "poloniex" {
+ return &Error{BadRequest, "invalid market name", fmt.Errorf("'%v' is not a valid market name", q.In.Market)}
+ }
+
+ return nil
+}
+
+func (q GetAllPortfoliosQuery) Run() (interface{}, *Error) {
+ u, err := db.GetActiveUsers()
+ if err != nil {
+ return nil, NewInternalError(err)
+ }
+
+ q.Out = make(map[string]Portfolio)
+
+ for _, marketConfig := range u {
+ report, err := GetWeekPortfolio(marketConfig)
+ if ErrorIs(err, NotFound) {
+ continue
+ }
+
+ if err != nil {
+ return nil, NewInternalError(err)
+ }
+
+ q.Out[marketConfig.User.Email] = report.Round()
+ }
+
+ return q.Out, nil
+}
{
"/admin",
[]Middleware{JwtAuth, UserConfirmed, UserIsAdmin, OtpAuth},
- []Route{},
+ []Route{
+ {"GET", []gin.HandlerFunc{AdminGetAllPortfolios}, "/portfolios"},
+ },
},
}
RunQuery(query, c)
}
+
+func AdminGetAllPortfolios(c *gin.Context) {
+ query := &GetAllPortfoliosQuery{}
+
+ query.In.Market = "poloniex"
+
+ RunQuery(query, c)
+}
}
type SignResult struct {
- Token string `json:"token"`
+ Token string `json:"token"`
+ IsAdmin bool `json:"isAdmin"`
}
func (s SignParams) Validate() *Error {
}
}
- return SignResult{token}, nil
+ return SignResult{token, newUser.Role == db.RoleAdmin}, nil
}
type SigninQuery struct {
return nil, NewInternalError(err)
}
- return SignResult{token}, nil
+ return SignResult{token, user.Role == db.RoleAdmin}, nil
}
type ConfirmEmailQuery struct {
"/change-password",
"/signout",
"/me",
+ "/admin",
"/account",
"/otp/enroll",
"/otp/validate",
--- /dev/null
+import Api from './api.js';
+import React from 'react';
+import {PFBalanceMinimal} from './balance.js';
+import Panel from './panel.js';
+
+class AdminDashboard extends React.Component {
+ constructor(state) {
+ super(state);
+ this.state = {'portfolios': null};
+ }
+
+ load = () => {
+ Api.Call('ADMIN_PORTFOLIOS', {}, function(err, status, data) {
+ if (err) {
+ console.error(err, data);
+ return;
+ }
+
+ this.setState({'portfolios': data});
+ }.bind(this));
+ }
+
+ componentDidMount = () => {
+ this.load();
+ }
+
+ render = () => {
+ if (this.state.portfolios === null) {
+ return <div></div>;
+ }
+ var portfolios = Object.keys(this.state.portfolios).map(function(email) {
+ return <div className="row" key={email}>
+ <div className="col-6"><span>{email}:</span></div>
+ <div className="col-6 text-center">
+ <PFBalanceMinimal variationP={this.state.portfolios[email].performance.variationP} balance={this.state.portfolios[email].value} periodStart={this.state.portfolios[email].periodStart}/>
+ </div>
+ </div>;
+ }.bind(this));
+
+ return <Panel component={<div>{portfolios}</div>} title="Portfolios Overview"/>;
+ }
+
+}
+
+export default AdminDashboard;
return '/otp/validate';
}
},
+ 'ADMIN_PORTFOLIOS': {
+ 'type': 'GET',
+ 'auth': true,
+ 'parameters': [],
+ 'buildUrl': function() {
+ return '/admin/portfolios';
+ }
+ },
+
};
Api.BuildRequest = function(endpointId, params) {
}
}
-export {PFBalance, Assets};
+class PFBalanceMinimal extends React.Component {
+ render = () => {
+ return <React.Fragment>
+ <div className="balance">
+ <div className="col-12">
+ <CurrencyLogo currency="BTC" /> <span><strong>{this.props.balance}</strong> <strong>{formatVariation(this.props.variationP)}</strong></span>
+ </div>
+ </div>
+ </React.Fragment>;
+ }
+}
+
+export {PFBalance, Assets, PFBalanceMinimal};
import OtpEnrollForm from './otp.js';
import PoloniexController from './poloniex.js';
import UserAccount from './account.js';
+import AdminDashboard from './admin.js';
import App from './app.js';
import Api from './api.js';
import cookies from './cookies.js';
</div>);
});
+App.page('/admin', true, function(context) {
+ App.mount(<div>
+ <AdminDashboard/>
+ </div>);
+});
+
App.page('/not_confirmed', true, function(context) {
App.mount(<div>
<div className="row">
UserId int64
Status MarketConfigStatus
Config map[string]string
+
+ // Will be expanded by pg
+ User User
}
func InsertMarketConfig(config *MarketConfig) error {
return &marketConfig, err
}
+
+func GetActiveUsers() ([]MarketConfig, error) {
+ var configs []MarketConfig
+
+ err := DB.Model(&configs).Column("User").Where("market_config.status=?", "enabled").Select()
+ if err != nil {
+ return nil, err
+ }
+
+ return configs, nil
+}